(Demo of issue added at CodePen, url given below)
In app.js I have my routings defined as..
$stateProvider
.state('login', {
url: '/login1',
templateUrl: 'templates/login.html',
controller: 'AuthSignUpCtrl'
});
and in login.html just to test I have called a method
{{test()}}
and in controller I have just created a test fn which just consoles & it gets called for 9-10 times
Note: I have verified, controller is getting loaded only once not multiple times. Also, If I add more routes in app.js the number of print keeps increasing as well.
Hope someone can help.
EDIT: controller fn
.controller('AuthSignUpCtrl', function($scope, $state) {
$scope.test = function() {
console.log(44)
};
});
Result:
controllers.js:72 44
controllers.js:72 44
2controllers.js:72 44
5controllers.js:72 44
controllers.js:72 44
controllers.js:72 44
4controllers.js:72 44
controllers.js:72 44
controllers.js:72 44
Issue demo: http://codepen.io/anon/pen/XXxxpM
Angular bindings will keep updating until it gets a stabilized value. Since your function is not returning anything and only doing a console, therefore it is being called multiple times. Try to return some string after console and it will not be called multiple times.
Related
I have verified, controller is getting loaded only once not multiple times. Also, If I add more routes in app.js the number of print keeps increasing as well.
Issue demo: http://codepen.io/anon/pen/XXxxpM (check console in browser)
.controller('AuthSignUpCtrl', function($scope, $state) {
var i=01;
$scope.test = function() {
console.log(i++);
};
});
$stateProvider
.state('login', {
url: '/login1',
templateUrl: 'templates/login.html',
controller: 'AuthSignUpCtrl'
});
I don't think your template is being reloaded.
I think its because you bound your function to an expression.
Try typing into the text box, this will cause the digest loop to cycle and will fire your function, resulting in more output in the console.
The relevant code:
var app = angular.module('client', [
'ngRoute'
,'controllers'
//,'proxyServices'
]);
app.config(['$routeProvider',
function($routeProvider){
$routeProvider
.when('/launch', {
templateUrl: 'partials/launch.html'
, controller: 'LaunchCtrl'
})
.otherwise({
redirectTo: '/launch'
});
}
]);
Note that I have proxyServices commented out. The launch page displays all fine and dandy.
Whenever I try to register it with my module, I end up getting the "uncaught object error" out of angular.js when angular attempts to load my 'client' module.
Here's my service...it's just a stub that does nothing right now; trying to minimize moving parts under my current test and ran into this stumbling block.
'use strict';
angular.module('proxyServices',[])
.factory('fooService', function() {
var serviceCall = function(){
return true;
}
return
{
events: function() { return serviceCall(); }
};
});
What did I do wrong?
Edit:
Well, I looked into the error from angular.js Line 78 and found this:
"[$injector:nomod] Module 'ngLocale' is not available! You either
misspelled the module name or forgot to load it. If registering a
module ensure that you specify the dependencies as the second
argument.
What's that mean?
Got it. Stupid error on my part.
I was trying to do too much under a single test and it took putting a breakpoint on line 78 of angular.js and decoding the error coming in rather than the message logging to the console to figure it out.
I put proxyServices in a new file; just before lunch.
I didn't register that new file as a script source in my parent html page.
As I said, stupid error. But the error that actually shows is very cryptic and had my attention diverted to the syntax of my service.
I have created a plnkr which demonstrates a problem that I am trying to solve. When you click the link in the plnkr, you will see a textfield. This textfield is bound with ng-model to myCtrl.foo, and in that controller is a $watch looking at the controller's foo property and then setting $scope.num to a random number. You will notice the random number never changes even though the watcher is clearly firing (via a console.log).
http://plnkr.co/edit/wpFPFeRC6CFFjLOa9QQw
Can anyone explain why this is not working, and what I can do to fix it?
Here is what happens
When you define your routes:
app.config(function ($stateProvider) { $stateProvider
.state('items', {
url: '/items/:item_id',
views: {
'my-view': {
controller: 'myController as myCtrl',
templateUrl: 'my-view.html'
},
'main#': {
controller: 'myController',
templateUrl: 'main.html'
},
}
})
});
you assign 2 different views to use the same controller, which is OK, but a controller in Angular is not a singleton. It is a constructor function. Meaning that both controllers (and their scope) will not be the same instance, but 2 different instances.
So the controller and the scope in view 1 will not be the same controller and scope as in view 2.
The controller will be instantiated twice with a different scope so the changes made in the scope of view 1 will not reflect the changes made in the scope of view 2 (as they have a different scope).
You can see this if you add the following lines to your controller:
app.controller('myController', function($scope) {
console.log('myController scope id: ' + $scope.$id);
console.dir($scope);
// Your code here
});
The log will show:
myController scope id: 003
myController scope id: 004
Possible solutions
Avoiding this boils down to personal preference. Here are some valid options:
use events to communicate between scopes and send an event when num is updated
use a service to store num centrally
store num in the $rootScope
Hope that helps!
Here is it working: http://plnkr.co/edit/tagldRNsgLXUhoGfZ2Un?p=preview
Did two things, first assigned all primitive bindings to an object called test. You can see why it is best to do this here: https://egghead.io/lessons/angularjs-the-dot
Second, put the controller around the views to ensure they share a scope and pulled it out of ui-router (as I know next to nothing about ui-router and whatever magic it does)
I am new to angular js and currently stuck with very wired kind of a bug. function in a controllers runs twice when its called by view loaded against a route.
http://jsfiddle.net/4gwG3/5/
you will see alert twice!!
my view is simple
and my app code is following
var IB = angular.module('IB', []);
//channel controller
IB.controller('channelsController', function ($scope, $routeParams) {
$scope.greet = function () {
alert('hi');
};
});
IB.config(function ($routeProvider) {
$routeProvider
.when('/channels', {
controller: 'channelsController',
template: '{{greet()}}'
})
.otherwise({ redirectTo: '/channels' });
});
First check that you're not initializing your Angular app twice (by having it initialized automatically with ng-app).
One time I had 2 html pages with ng-app (one for login.html and
another for main.html) and this was a problem I realized later.
Second and for me the most important, check if you have attached your controller to multiple elements. This is a common case if you are using routing.
In my case I was navigating to DashboardController like so:
app.config(function($routeProvider){
$routeProvider
.when('/', {
controller: 'DashboardController',
templateUrl: 'pages/dashboard.html'
})
});
But I also had this in dashboard.html:
<section class="content" ng-controller="DashboardController">
Which was instructing AngularJS to digest my controller twice.
To solve it you have two ways:
removing ng-controller from your html file like this:
<section class="content">
or removing controller from routing (that is normally situated in app.js):
app.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'pages/dashboard.html'
})
});
I think by creating an interpolation {{greet()}}, you create a watch on function greet. This function can get call as many time as digest cycle runs, so it is not a question about it running 1 or 2 times. So you should not depend upon the times the function is called.
I dont know what you are trying to achieve here. There are two alerts
1. When the controller is called.
2. When the template is get evaluated.
template is to provide the view part, however, in this case template is just evaluating function which is not creating any view.
I had the same problem, so I did:
$scope.init=function()
{
if ($rootScope.shopInit==true) return;
$rootScope.shopInit=true;
...
}
$scope.init();
Like if it were a singleton ! (I had many ajax calls each time I display, it was boring)
I'm using angular.js on IE8.
I'm getting: "10 $digest() iterations reached. Aborting!" runtime error when using "$locationProvider.html5Mode(true);" on my controller.
My Code:
angular.module('MyApp', [], function ($routeProvider, $locationProvider) {
$routeProvider.when('/Get', {
templateUrl: 'Template/T1.html',
controller: RouteCtrl
});
$routeProvider.when('/GetT2/T2', {
templateUrl: 'Template/T2.html',
controller: RouteCtrl
});
$locationProvider.html5Mode(true);
});
function MainCntl($scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
$scope.$location.path('/Get');
}
function RouteCtrl($scope, $route) {
$scope.params = $route;
}
UPDATE:
T1 and T2 doesn't contain anything related to angular.
T1.html:
<h1>T1</h1>
<p>T1</p>
T2.html:
<h1>T2</h1>
<p>T2</p>
Here is where I use my controller:
<div id="content" ng-controller="MainCntl">
<div ng-view></div>
</div>
I don't know how relevant this is for your problem, but we had the same symptoms, also from html5 mode. We were manually bootstrapping, and also during that process adding class="ng-app" to the html element. This caused two angular instances to run, one which we configured (with html5mode on), and another with the default settings.
So the two instances would fight over the contents of $location and it would never reach equilibrium.
The solution was to ensure that the html element is "pristine" when we bootstrap manually.
Note: we are using require.js, and it became especially evident with the asynchronous loading of elements.
Im guessing that you are running into an infinite loop somewhere.
I am going to make some assumptions because there is no html code for me to see how controllers are being placed, but this should give you an idea what to look out for.
Im going to assume, that templateUrl: 'Template/T1.html', contains a MainCntl.
On page load, your $scope.$location.path('/Get'); is being called inside MainCntl.
This kind of situation would cause a loop --- everytime the page loads, you are loading a controller that is changing the location to the same page, which is loading the controller... etc etc.
10 $digest() iterations reached. Aborting! comes from these kinds of loops.