I use ui-router to route to particular sub page as needed:
var myApp = angular.module("myApp",['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('usergroups', {
url: "/usergroups",
templateUrl: "pages/usergroups.html",
controller : 'UsergroupsCtrl'
})
.state('usergroups.create', {
url: "/create",
templateUrl: "pages/usergroups.new.html",
controller : 'UsergroupsCtrl'
})
...
This is my usergroups.html:
<body>
<h3>User Groups</h3><br/>
<button class="fon-btn" type="button" ng-hide = "toAdd" ng-click="toAdd = true" ui-sref="usergroups.create">Create New Group</button>
<div ui-view></div>
<ul>
<li class="bitcard padding10" ng-repeat="group in usergroups">
<span class="padding10"><strong>{{group.name}}</strong></span>
</li>
</ul>
</body>
and usergroups.new.html:
<body>
<form ng-submit="add()">
<input class="btn" type="submit" value="Add Usergroup"><br/><br/>
</form>
</body>
When I click on Add Usergroup, it will called add() from UsergroupsCtrl:
$scope.add = function() {
$scope.usergroups.push({name:$scope.name});
console.log($scope.usergroups);
}
The console show that $scope.usergroups is already updated. but somehow in usergroups.html: ng-repeat="group in usergroups" did not update the view. I add $scope.$apply() and $scope.$digest() but got an error:
$apply already in progress
But everything works fine if I did not use ui-router. How can I resolve this?
I think same $scope cannot be used in two different controllers. you can change it to $rootScope. like $rootScope.usergroups.push(). This SO may help you. You can use $stateParam also.
Related
I am very new to AngularJS. This is my first project so please forgive me if my question is very basic.
I am created a page using simple HTML and put three button on it.
On these button click I want to load views in the lowel part of screen.
Index.html
<body ng-app="MyApp">
<div class="tab" ng-controller="TabControlController">
<button class="tablinks" onclick="openTab(event, 'Environments')" ng-click="Views/EnvironmentsView.html">Environments</button>
<button class="tablinks" onclick="openTab(event, 'SIT_Downloader')" ng-click="Views/SITDownloaderView.html">Download PCP Client</button>
<button class="tablinks" onclick="openTab(event, 'Users')">PCP Users</button>
</div>
<div id="Environments" class="tabcontent" ng-controller="environmentController">
<div>
<div ng-view></div>
</div>
</div>
<div id="SIT_Downloader" class="tabcontent" ng-controller="SITDownloaderController">
<div>
<div ng-view></div>
</div>
</div>
<div id="Users" class="tabcontent">
<div>
<div ng-view></div>
</div>
</div>
</body>
Bootstrap.js
var MyApp= angular.module('MyApp', ['ngRoute'])
.config(function($routeProvider) {
$routeProvider
.when('/',
{
templateUrl: 'Views/EnvironmentsView.html',
controller: window.environmentController
})
.otherwise({ redirectTo: '/' });
});
views are very simple as of now...
<h3>PCP Users</h3>
<p>This screen will be used to add/remove users</p>
Can anyone help me to understand what I am missing here or redirect me to some page with full example of this.
This is single page application.
You can try instead of calling a function onclick of a button ,just link the route with anchor tag
Maintain the routes in separate js file
like:
(function() {
'use strict';
angular.module('app.home').config(appRoutes);
appRoutes.$inject = ['$routeProvider', '$locationProvider'];
function appRoutes($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '../yourhtmlfile.html',
controller: 'controllerName',
resolve: {}
})
}
})();
Also you dont need to have multiple ng-view for each view
have a single ng-view
<div>
<div ng-view></div>
</div>
this helps in loading the html page when you click on the tag and loads the corresponding html file.
You have some problem in your sample.
1- change <button ng-click=".." ></button> to
you can use button also but you should crate a function that changes the current route to new route.
<button ng-click="changeRoute('/home')" >Home</button>
$scope.changeRoute = function(newRoute){
$location.path(newRoute);
}
2- wrong syntax for define controller in route.(put controller in each route)
3- Don't need to multiple ng-view
Demo
I thought this should be something easy because I've done it before, but apparently the first time I got lucky, either that or Angular has some quirks I have not yet wrapped my head around.
What I'm trying to do is be able to edit a customer order. All customer orders are sent to the client from the database as JavaScript objects, using PHP.
That is fine, my problem is within Angular when I want to edit these orders, through a modal window (which has its own scope). Basically a form pops up in the modal that asks the user to edit the Javascript object, of course however no user wants to edit a raw object so it's a form with ng-models tied to that object. My problem is the ng-model doesn't seem to pick up my object reference.
So here we go (I have a plunker below):
This is the controller that fetches the customer order on the page the first time (before the user initiates the modal to edit the order):
controller: function($scope,$http,$stateParams,$uibModal) {
$http({
method: 'GET',
url: 'http://example.com/orderDATA',
params: {id: $stateParams.id}
}).then(function successCallback(html) {
html.data[0].orderProperties = JSON.parse(html.data[0].orderProperties); //format data from server so that JavaScript can play with it
$scope.order = html.data[0];
$scope.edit = function (order) //function that launches modal window
{
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'EditOrderInstance.html',
controller: 'EditOrderCtrl',
scope: $scope,
size: "lg",
resolve: {
order: function() {
return order;
}}
});
}
});
}
The edit() function is called like so from the following template:
<div class="container" style="margin-top:2%;">
<div class="row">
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy">Customer Name : #{{order.orderProperties.firstName + " " + order.orderProperties.lastName}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy">Pickup : #{{order.orderProperties.pickupDate + " in " + order.orderProperties.location}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy"><i class="fa fa-envelope" aria-hidden="true"></i> : #{{order.orderProperties.email}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy"><i class="fa fa-phone" aria-hidden="true"></i> : #{{order.orderProperties.phone}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<button type="button" style="border-radius:0;" class="btn btn-warning" ng-click="edit(order)">Edit This Order</button> <button type="button" style="border-radius:0;" class="btn btn-danger">Delete or Refund This Order</button> <button type="button" style="border-radius:0;" class="btn btn-primary">Complete This Order</button>
</div>
</div>
</br></br>
<div class="shipping whiteNoPointy text-center" ng-repeat="specific in order.order">
<div class="col-xs-12" ng-if="specific.quantity.value>0"><p>#{{specific.quantity.value}} #{{specific.Name}}</p></div>
</div></div>
This part works fine. However, when I do hit the edit function, that takes us into a new scope and a new controller, specifically the one below:
app.controller('EditOrderCtrl', ['$scope', '$http', '$uibModal','$uibModalInstance', 'order', function($scope, $http, $uibModal, $uibModalInstance, order) {
$scope.order = order;
So as is hopefully clear, all I did was pass the order object to the modal.
Now to me, all I've done is pass the same order object around, and now to this new controller. But the problem is that when I investigate this latest order it has no $$hashkey. I say this because of the problem that follows, as I said I did this before except in that instance I passed the order object from inside an ng-repeat, and the last step worked. But here when I do it it doesn't work.
What I mean is, when I try to have the models in the modal template line up with the order object passed to the modal's controller, they don't. I just get blank inputs, which isn't good because to edit a customer order you need to now what the current order is, otherwise it's like you are starting over.
Here is the template with the ng-model.
<script type="text/ng-template" id="EditOrderInstance.html">
<div class="modal-header" style="text-align:center;">
<h3 class="modal-title">Edit Order</h3>
</div>
<div class="modal-body" style="text-align:center;">
<form name="order" novalidate>
<label for="firstName">First Name</label>
<input type="text" name="firstName" class="form-control" ng-model="order.orderProperties.firstName" ng-minlength="2" required>
<p ng-show="orderorderProperties.firstName.$error.minlength" class="warning">Please put your full first name.</p>
</div>
<button ng-disabled="order.$invalid||totalPrice===0" ng-click="submitOrder()" class="btn btn-default">Submit</button>
</form>
</div>
<div class="modal-footer" style="text-align:center;">
<button class="btn toggledz" type="button" ng-click="save()">Submit</button>
<button class="btn" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
Notice the order.orderProperties.firstName ng-model. This is there, I console log it from the modal's controller and I can see it is set, but the model is blank. So why is this the case? Why did it work before when the console.log() showed the object was passed with a $$hashkey? I can't pass from an ng-repeat again because I only have one order, so there is nothing to iterate over in the first template.
Please assist. I need to be able to edit the order using ng-model, so that the admin can edit the order and send a new order object back to my server.
Edit: Added a plunker: https://plnkr.co/edit/x6FPiS6OtF2gdn4ZtFyJ?p=preview
From the first look, the problem appears to be with your resolve function
controller: function($scope,$http,$stateParams,$uibModal) {
$http({
method: 'GET',
url: 'http://example.com/orderDATA',
params: {id: $stateParams.id}
}).then(function successCallback(html) {
html.data[0].orderProperties = JSON.parse(html.data[0].orderProperties); //format data from server so that JavaScript can play with it
$scope.order = html.data[0];
$scope.edit = function (order) //function that launches modal window
{
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'EditOrderInstance.html',
controller: 'EditOrderCtrl',
scope: $scope,
size: "lg",
resolve: {
order: function() {
return $scope.order;
}}
});
}
});
}
Your resolve function for order should return $scope.order
Try it and let me know if this works. I am just going with the instincts
I got it to work by changing the variable name, I guess for some reason it was looking to the old $scope.order instead of the one resolved to the modal?
Anyway, here is a working plunker...
https://plnkr.co/edit/AZpeFGaBktFjSr2SL2Rv?p=preview
Currently, I'm working on an initial AngularJs app for an Admin Console for a database. I'm pretty new at Angular, so I've started off by modifying the phonecat tutorial. Basically, I've got a Jersey REST API that I need to make calls against in Angular. CORS is not the problem, they're both running on the same Tomcat.
The data structure is Projects have Groups within them.
I can redirect from Login to the Projects list page, the controller for getting the list of projects is called, and I can click a project and get the details page and its controller is called. But when I click a link from the project-details page and have it redirect to the groups-list page, the REST api call is never made (according to Chrome's network monitor.)
I'm rather confused because hypothetically it should be the exact same as the projects list.
Controllers:
phonecatControllers.controller('ProjectListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/project?show_hidden=true').success(function(data){
$scope.projects = data.hits.hits
});
$scope.orderprop='timeModified';
}]);
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
$scope.orderprop='timeModified';
}]);
phonecatControllers.controller('ProjectDetailCtrl', ['$scope', '$routeParams' ,'$http', function($scope, $routeParams, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/project/'+$routeParams.projectId).success(function(data){
$scope.project=data;
});
}]);
project-details.html:
<img ng-src="{{project._source.imageUrl}}" class="project">
<h1>{{project._source.name}}</h1>
<p>{{project._id}}</p>
<ul class="specs">
<a ng-href="#/groups" ng-click=>Group IDs</a>
<dd ng-repeat="group in project._source.groupIDs">{{proj._source.name}}
{{group.groupID}}
</dd>
</ul>
group-list.html
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<!--Sidebar content-->
Search: <input ng-model="query">
Sort by:
<select ng-model="orderprop">
<option value="name">Alphabetical</option>
<option value="dateModified">Newest</option>
</select>
</div>
<div class="col-md-10">
<!--Body content-->
<ul class='groups'>
<li ng-repeat="group in groups | filter:query | orderBy:orderprop" class="thumbnail">
<img ng-src=" {{group._source.imageUrl}}" alt="{{group._source.name}}">
{{group._source.name}}
<p>{{group._source.timeModified}}</p>
</li>
</ul>
</div>
</div>
</div>
app.js
'use strict';
/* App Module */
var phonecatApp= angular.module('phonecatApp', [
'ngRoute', 'phonecatControllers', 'phonecatFilters']
);
phonecatApp.config(['$routeProvider',
function($routeProvider){
$routeProvider.when('/projects',
{
templateUrl: 'partials/project-list.html',
controller: 'ProjectListCtrl'
}).when('/projects/:projectId', {
templateUrl: 'partials/project-detail.html',
controller: 'ProjectDetailCtrl'
}).when('/home', {
templateUrl: 'partials/login.html',
controller: 'LoginCtrl'
}).when('/groups',
{
templateUrl: 'partials/group-list.html',
controller: 'GroupListCtrl'
})
.otherwise({
redirectTo: '/home'
});
}]);
I've even tried to take an approach where the projectID is a routeParam (kind of like for Project details), but still no luck.
Let me know if you anything else to answer my question. I know it's going to be something so stupidly simple that a handprint will appear on my forehead. (From what I've seen, possibly a space where it's not supposed to be.)
Thanks!
<a href="#/groups/{{group._id}}" class="thumb"> should be <a ng-href="/groups/{{group._id}}" class="thumb">
Also <a ng-href="#/groups" ng-click=>Group IDs</a should not have an empty ngClick on it. It should look like <a ng-href="/groups">.
So basically just change the attribute of the link from href to ng-href and then remove the # symbol from the link.
You have:
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
$scope.orderprop='timeModified';
}]);
I would instead do this in your controller:
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http) {
$scope.function_name = function() {
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
}
$scope.orderprop='timeModified';
}]);
For your link that is within the HTML element possessed by the controller,
<a ng-href="/groups" ng-click="function_name()">Group IDs</a>
As it is, your AJAX call is just sitting there. You need to place it within a block where code is executed for it to be called, just like in any other case. In this case, you must place it within a function that serves as a callback tied to ng-click.
I am new to Angular. I went to intro-tutorials on some website.
There I learned that I can access controller functions and controller-local variables using controller-name and without $scope service. Like for example:
<div ng-controller="someController">
someController.someFunction()
someController.someVariable
</div>
I my simple application I have written a controller in controllers.js and using it in home.html. I have defined the mapping in app.js
I provided a button tag for it in html but the controller function is just not responding.
Looking at my js and HTML page you will know what I am trying to accomplish.
Here' controllers.js:
app.controller('welcomeStoryPublishCtrl', ['$log','$http',function($log,$http){
this.wsPublish = {};
this.publishGroup = function(wsPublish){
console.log('here');
$http({
method:'POST',
url: 'http://localhost:9090/Writer/publishStory',
header: {'Content-Type':'application/json'},
data: wsPublish
});
};
this.public = function(){
console.log('from public');
};
}]);
home.html
<html>
<head>
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js" ></script>
<script src="https://jspm.io/system#0.16.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<div>
<div id="welcomeStory">
<span id="wsTitleBub">Title</span>
<input id="wsTitle" type="text" ng-model="wsPublish.welcomeStoryTitle" />{{wsPublish.welcomeStoryTitle}}
<h6>Words..</h6>
<textarea id="wsWords" ng-model="wsPublish.welcomeStoryWords"></textarea>
<input id="wsPublish" type="button" name="wsPublish" value="Publish" ng-click="pub = !pub" />
<input id="wsAddShelf" type="button" name="wsAddToShelf" value="Add To Shelf" ng-click="addToShelf()" />
</div>
<div id="wsPublishTo" ng-show="pub">
<ul>
<li>
<input type=submit id="wsgroups" value="Group" ng-click="publishGroup(wsPublish)" />
</li>
<li>
<button id="wsPublic" ng-click="public()">Public</button>
</li>
</ul>
</div>
</div>
</body>
</html>
I know that I can do this by injecting $scope module dependency and I know controller instantiation always creates a $scope object itself.
But what if try doing so like this? What am I doing wrong here?
And here is app.js:
angular.module('Writer', ['AllControllers','ngRoute'])
.config(['$routeProvider', function($routeProvider,$Log){
$routeProvider.when('/Diary',{
templateUrl:'pages/login.html',
controller: 'LoginFormController'
})
.when('/loginPg',{
template: 'Hello from app.js'
})
.when('/home',{
templateUrl: './pages/home.html',
controller: 'welcomeStoryPublishCtrl'
})
.otherwise({redirectTo : '/Diary'});
}]);
First off all your input elements are not wrapped in a <form> tag and this is why your button should not be working properly. If you insist to use <button> it should be in a <form> tag so it "submits" the form, if not, go with <input type="submit"..>
Lastly, i would suggest you to use services for your http requests as this is a common good practice. :)
In your HTML you have not mentioned the ng-app directive neither have you mentioned your controller directive ng-controller.
Your HTML
<body ng-app="someApp">
<div>
<div id="welcomeStory" ng-controller="welcomeStoryPublishCtrl as wsCtrl">
<!-- Rest of your code -->
<button ng-click="wsCtrl.public()">Public</button>
Your JS
var app = angular.module('someApp', []);
app.controller('welcomeStoryPublishCtrl', ['$log','$http',function($log,$http){
this.wsPublish = {};
this.publishGroup = function(wsPublish){
console.log('here');
$http({
method:'POST',
url: 'http://localhost:9090/Writer/publishStory',
header: {'Content-Type':'application/json'},
data: wsPublish
}).success(function(data){
console.log('run success!');
});
};
this.public = function(){
console.log('from public');
};
}]);
Hope this helps.
Are you missing ng-app attribute ?
im new to angular and was struck linking dropdown selected to ng-click button
<div class="col-xs-2">
<select name="cars" ng-model="dropdown_data">
<option>email</option>
<option>phone</option>
<option>username</option>
</select>
</div>
<br />
<div class="col-xs-4">
<button type="button" class=" " data-ng-click="search_{{dropdown_data}}()">Search</button>
</div>
<script>
var ng = angular.module('myApp', []);
ng.controller('ctrl', function($scope, $http) {
$scope.search_phone = function() {
alert("phone")
}
$scope.search_email = function() {
alert("email")
}
})
</script>
this seems to be fairly simple but im not sure what im doing wrong...Im not able to show alerts depending on selected dropdown
Plunker link http://plnkr.co/edit/Iicm9tvfizXxNl3MwtZI?p=preview
any help is much appriciated...thanks in advance
There were few things that you needed in the plunkr.
Firstly you need to define on the HTML that it is in fact an Angular Application (via the ngApp attribute).
Secondly you need to define a controller for your view (via the ngController attribute).
Once you have those things in place, you need to understand what this would do
ng-click="search_{{dropdown_data}}()"
If you think about how ng-click works, it registers a function on click. This happens on the compile phase of a directive (as you can see on its sourcecode).
This means that when the directive compiles, it will register the function with the name search_{{dropdown_data}} and even though the dropdown_data will be interpolated later on when its value changes, the originally bound function won't update.
However if you had dropdown_data as an attribute or as a key to a map of functions that will work. Here an example of how you may do that:
$scope.search = {
phone: function() {
alert("phone")
},
email: function() {
alert("email")
}
};
and on the button: data-ng-click="search[dropdown_data]()"
Here a working plunkr: http://plnkr.co/edit/u4vJj2a0r1a95w64crHM?p=preview
I am also new in angular but have used same functionality without search button direct given anchor link try this if you need,
<div ng-app="myApp">
<div ng-controller="setContent">
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Subject
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li ng-repeat="a in subjects">{{a}}</li>
</ul>
</div>
var app = angular.module('myApp', []);
app.controller('setContent', function($scope, $http) {
$scope.subjects = ['Math', 'Physics', 'Chemistry', 'Hindi', 'English'];
});
});
The problem is this data-ng-click="search_{{dropdown_data}}()". Better to pass a value to the function like this:
<button type="button" data-ng-click="search(dropdown_data)">Search</button>
$scope.search = function(type) {
alert(type)
}
also dont forget ng-app and ng-controller.
see the plunker