Tried to Load Angular More Than Once - javascript

I have a yeoman scaffolded app (the angular fullstack generator).
grunt serve works fine, but grunt build produces a distribution that locks up memory, most probably because of circular references in angular.
I upgraded angular to 1.2.15. The error I get is:
WARNING: Tried to Load Angular More Than Once
Prior to upgrading, the error was:
Error: 10 $digest() iterations reached. Aborting!
It's pretty difficult to debug as it only happens after build / minification. All my modules are in angular's array format, so the minification DI shouldn't be a problem but it is.
There's no single script that causes this. The only way it goes away is if I don't initialize with my app.js file. My app.js file is below.
Any thing come to mind?
'use strict';
angular.module('myApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
'ngTagsInput',
'ui.bootstrap',
'google-maps',
'firebase'
]);
angular.module('myApp').config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/listing.html',
controller: 'ListingCtrl'
})
.otherwise({
redirectTo: '/'
});
}]).constant('FIREBASE_URL', 'something');

This could be a number of issues: essentially it's a problem of routeProvider not finding a file and recursively loading the default.
For me, it turned out that it wasn't minification but concatenation of the js that caused the problems.
angular.module('myApp').config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/listing.html',
controller: 'ListingCtrl'
})
.otherwise({
redirectTo: '/'
});
}]).constant('FIREBASE_URL', 'something');
You'll notice that if the app can't find a file (i.e., otherwise), then it will redirect to the root, which in this case loads the templateUrl. But if your templateUrl is wrong, then it will cause a recursion that reloads index.html loading angular (and everything else) over and over.
In my case, grunt-concat caused the templateUrl to be wrong after build, but not before.

The problem could occur when $templateCacheProvider is trying to resolve a template in the templateCache or through your project directory that does not exist
Example:
templateUrl: 'views/wrongPathToTemplate'
Should be:
templateUrl: 'views/home.html'

This doesn't have anything to do with app.js at all. Instead, this warning is logged when you include the Angular JS library more than once.
I've managed to reproduce the error in this JSBin. Note the two script tags (two different versions):
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
Relevant Angular code at GitHub.

Seems like nobody has mentioned this anywhere so here is what triggered it for me:
I had the ng-view directive on my body. Changing it like so
<body layout="column">
<div ng-view></div>
...
</body>
stopped the error.

I was also facing such an issue where I was continously getting an infinite loop and the page was reloading itself infinitely. After a bit of debugging I found out that the error was being caused because, angular was not able to load template given with a particular id because the template was not present in that file.
Be careful with the url's which you give in angular apps. If its not correct, angular can just keep on looking for it eventually, leading to infinite loop!
Hope this helps!

I had the same issue, The problem was the conflict between JQuery and Angular. Angular couldn't set the full JQuery library for itself. As JQLite is enough in most cases, I included Angular first in my web page and then I loaded Jquery. The error was gone then.

In my case I was getting this error while using jquery as well as angular js on the page.
<script src="http://code.jquery.com/jquery-2.1.3.min.js" type="text/javascript"></script>
<script src="js/angular.js" type="text/javascript"></script>
<script src="js/angular-route.js" type="text/javascript"></script>
I removed :
<script src="http://code.jquery.com/jquery-2.1.3.min.js" type="text/javascript"></script>
And the warning disappeared.

Had this problem today and figured I would post how I fixed it. In my case I had an index.html page with:
<body ng-app="myApp" ng-controller="mainController"
<div ng-view></div>
</body>
and in my app.js file I had the following code:
$routeProvider.when('/', {
controller : 'mainController',
templateUrl : 'index.html',
title : 'Home'
}).when('/other', {
controller : 'otherController',
templateUrl : 'views/other.html',
title : 'other'
}).otherwise({
redirectTo : '/'
});
As a result, when I went to the page (base_url/) it loaded index.html, and inside the ng-view it loaded index.html again, and inside that view it loaded index.html again.. and so on - creating an infinite recursive load of index.html (each time loading angular libraries).
To resolve all I had to do was remove index.html from the routProvider - as follows:
$routeProvider.when('/other', {
controller : 'otherController',
templateUrl : 'views/other.html',
title : 'other'
}).otherwise({
redirectTo : '/'
});

I had a similar issue, and for me the issue was due to some missing semicolons in the controller. The minification of the app was probably causing the code to execute incorrectly (most likely the resulting code was causing state mutations, which causes the view to render, and then the controller executes the code again, and so on recursively).

I had that problem on code pen, and it turn out it's just because I was loading JQuery before Angular. Don't know if that can apply for other cases.

Capitalization matters as well! Inside my directive, I tried specifying:
templateUrl: 'Views/mytemplate'
and got the "more than once" warning. The warning disappeared when I changed it to:
templateUrl: 'views/mytemplate'
Correct me, but I think this happened because page that I placed the directive on was under "views" and not "Views" in the route config function.

This happened to me too with .NET and MVC 5 and after a while I realized that within the label on Index.cshtml file:
<div data-ng-view=""></div>
again included as section scripts happens to you. To solve the problem on the server side what I do is return the partial view. Something like:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Login()
{
return PartialView();
}
public ActionResult About()
{
return PartialView();
}
}

I had this same problem ("Tried to Load Angular More Than Once") because I had included twice angularJs file (without perceive) in my index.html.
<script src="angular.js">
<script src="angular.min.js">

I have the same problem, because I have angular two times in index.html:
<script src="https://handsontable.github.io/ngHandsontable/node_modules/angular/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
Note that the warning arises only when html5 mode is true, when my html5 mode was false, I did not see this warning.
So removing the first angular.js solves the problem.

You must change angular route '/'! It is a problem because '/' base url request. If you change '/' => '/home' or '/hede' angular will good work.

For anyone that has this issue in the future, for me it was caused by an arrow function instead of a function literal in a run block:
// bad
module('a').run(() => ...)
// good
module('a').run(function() {...})

In my case I have index.html which embeds 2 views i.e view1.html and view2.html. I developed these 2 views independent of index.html and then tried to embed using route.
So I had all the script files defined in the 2 view html files which was causing this warning. The warning disappeared after removing the inclusion of angularJS script files from views.
In short, the script files angularJS, jQuery and angular-route.js
should be included only in index.html and not in view html files.

Another case is with Webpack which concating angular into the bundle.js, beside the angular that is loaded from index.html <script> tag.
this was because we used explicit importing of angular in many files:
define(['angular', ...], function(angular, ...){
so, webpack decided to bundle it too. cleaning all of those into:
define([...], function(...){
was fixing Tried to Load Angular More Than Once for once and all.

My problem was the following line (HAML):
%a{"href"=>"#", "ng-click" => "showConfirmDeleteModal()"} Delete
Notice that I have a angular ng-click and I have an href tag which will jump to # which is the same page. I just had to remove the href tag and I was good to go.

The problem for me was, I had taken backup of controller (js) file with some other changes in the same folder and bundling loaded both the controller files (original and backup js). Removing backup from the scripts folder, that was bundled solved the issue.

I had this problem when missing a closing tag in the html.
So instead of:
<table></table>
..my HTML was
<table>...<table>
Tried to load jQuery after angular as mentioned above. This prevented the error message, but didn't really fix the problem. And jQuery '.find' didn't really work afterwards..
Solution was to fix the missing closing tag.

I was having the exact same error. After some hours, I noticed that there was an extra comma in my .JSON file, on the very last key-value pair.
//doesn't work
{
"key":"value",
"key":"value",
"key":"value",
}
Then I just took it off (the last ',') and that solved the problem.
//works
{
"key":"value",
"key":"value",
"key":"value"
}

Related

Lazy loading controller from separate file using state provider

So, I'm trying to dynamically load a file that adds a controller to my main module. The thing is that I don't want to reference the file itself in a script tag.
To be more specific, I have 2 controller files. The main controller file mainController.js referenced in my index.html file. Any controller that I add to that file loads without issues.
The controller file I want to use for my login page login.js, contains the following information:
function LoginCtrl($http){
console.log("Controller loaded");
};
angular
.module('inspinia')
.controller('LoginCtrl', LoginCtrl);
All my controller files are in the same folder, however, contrary to the mainController.js, the login.js file does not appear inside any .html file.
My intention was to load the login.js file dynamically inside my stateProvider like this:
$stateProvider
...
.state('logins', {
url: "/logins",
templateUrl: "views/login.html",
controller: LoginCtrl,
data: { pageTitle: 'Login', specialClass: 'gray-bg' },
resolve: {
loadPlugin: function($ocLazyLoad) {
return $ocLazyLoad.load ({
name: 'inspinia.LoginCtrl',
files: ['js/controllers/login.js']
});
}
}
})
...
So long as I dont try to dynamically load the login.js file (so adding a reference to the file in a .html file or adding the login controller code inside the mainController.js file) everything works. But as soon as I try to remove the references to force the stateProvider to take care of the loading I get an Error: $injector:modulerr
Anyone knows what's the proper way to call the lazyLoader so I can only load my .js files when I need them?
EDIT info:
Something that I forgot to mention: The file-loading part itself seems to be working. If I do not call the controller anywhere and only load it. I can see the controller file being loaded by the browser. But the problem seems to be a timing issue. If I mention the controller name inside the .state() angular tries to access it before it gets loaded and the whole thing crashes before even loading the file
I recomend you to look over the ocLazyLoad to see how a controller is declared and loaded with ui-router resolve state property:
https://oclazyload.readme.io/docs/with-your-router
Basically, I think that what is missing in your approach is to use the string controller declaration, not the function one:
$stateProvider
...
.state('logins', {
url: '/logins',
templateUrl: 'views/login.html',
controller: 'LoginCtrl as login',
data: {
pageTitle: 'Login',
specialClass: 'gray-bg'
},
resolve: {
loadPlugin: function($ocLazyLoad) {
return $ocLazyLoad.load('js/controllers/login.js');
}
}
})
...
A tip that is important to use is: simplify the first implementation of something that you didn't used before. Your example shows a lot of parameters on the ocLazyLoad service. Try to load first the main element that you need, progressively adding one after the other after it succeeds because, sometimes, you may be on the right track and something like this, which you're unaware of, can lead you to a loooooong debug routine.
Also, take a look at the example below:
https://github.com/ocombe/ocLazyLoad/tree/master/examples/complexExample
It has a state declaration very similar to yours. Compare each other and modify to suit your needs.

The $routeProvider in Angular can't be found in undefined

I'm following a guide on how to include AngularJS in a MVC project and I got to the point where I'm connecting my controllers (the section's name is Routing).
It seems not to work and when I open the console, I see the following error message.
TypeError: Cannot read property '$routeProvider' of undefined
I've checked all the files in the solution for that string and the only usage of it is in the file where I registered my module. It looks like this.
var CoolApp = angular.module('CoolApp', ["ngRoute"]);
CoolApp.controller('CoolController', CoolController);
var configFunction = function ($routeProvider) {
$routeProvider
.when("/one", { templateUrl: "angularRoute/first" })
.when("/two", { templateUrl: "angularRoute/second" })
.when("/thr", { templateUrl: "angularRoute/third" });
}
configFunction.$inject["$routeProvider"];
CoolApp.config(configFunction);
I have MVC controller class named AngularRouteController and as far I can see, the only place where I'm "dotting" the $routeProvider is in when statements. Commenting them out doesn't resolve my issue, though. Instead, the line that seems to be the cause of the error is this one.
configFunction.$inject["$routeProvider"];
Due to my ignorance with Angular, I can't see why. As a consequence, I have no idea how to solve the problem. Any suggestions would be welcome. I've googled the issue but that didn't give me anything useful (as far I could judge).
The closest hits I've got was this and this one and they didn't make me any wiser. Not even sure if those are relevant to my problem.
I've made sure that I reference the routing package of Angular separately as suggested in this answer. Should I skip ngRoute and go for ui.router? Not sure what that changes for the guide...
It looks like you have to change that line to:
configFunction.$inject = [
"$routeProvider"
];

Angular: [$injector:modulerr] Failed to instantiate module

I've been trying to set up basic AngularJS functionality for a project but have been hitting a brick wall when it comes to including angular-route. Both are version 1.4.8. I'm currently using gulp-require to concatenate my JS, here's my main javascript file
// =require ../components/jquery/dist/jquery.min.js
// =require ../components/angular/angular.js
// =require ../components/angular-route/angular-route.js
$(document).ready(function() {
// =require app/app.js
}); // Doc ready is done!
And my app.js file
var app = angular.module('myApp', ['ngRoute']);
app.controller("ctrl", ["$scope", 'ngRoute', function($scope) {
$scope.test = "It works!";
}]);
I've checked and all the files are concatenating properly. The ng-app and ng-controller attributes are on my HTML file. I've tried adding and removing the ngRoute injection and switching the order of the files but to no avail. It's frustrating since I used Angular 1.4.5 in almost the exact same way without these issues popping up but I can't replicate the same here even when going back. But the {{test}} variable in my HTML is still not rendering, and basic operations like {{2 + 3}} aren't either.
EDIT: here is the link to the original error message I'm currently receiving: http://tinyurl.com/zx3k85f
EDIT 2: The parts of my HTML code that's calling the app and the controller:
<html lang="en" ng-app="myApp">
<body ng-controller="ctrl">
</body>
</html>
I'm using nunjucks for HTML dynamic generation, although I've changed the syntax for this so it doesn't conflict with Angular's double curly braces.
You can't inject module as dependency inside controller, you should remove 'ngRoute' from the controller DI inline array.
app.controller("ctrl", ["$scope", , function($scope) {
Update
Basically the real problem is you are loading your angular component script using requirejs(lazily), so while you are having ng-app="myApp" with module name start looking for myApp module, and the module has not loaded therefore it throws an error .
So I'd recommend you to don't use ng-app directive to start angular on page load. Instead you should wait until all the scripts related to angular loaded, & then to bootstrap angular app lazily using angular.bootstrap method.
Code
$(document).ready(function() {
requirejs(["app/app.js"], function(util) {
angular.bootstrap(document, ['myApp']);
});
});
ngRoute is a provider that needs to be configured in the module config section before being used. Using it within a controller does not make any sense. Here the version that will work:
angular.module('myApp', ['ngRoute']);
angular.module('myApp').controller("ctrl", ["$scope",function($scope) {
$scope.test = "It works!";
}]);
Moreover, you need to call your module using directive ng-app=myapp in the html element where you plan to render your app.

AngularJS ignore routing by ui.route

I try change build-in Angular route mechanism to ui.router. So I included angular.ui.router.js to my index.html and to my module:
var app = angular.module('multibookWeb', ['ui.router']);
Next I set routing in app.config:
$urlRouterProvider.otherwise('/list');
$stateProvider
.state('list', {
url: '/list',
templateUrl: '/partials/list/list.html',
});
Console don't show any errors, but routing doesn't work. I fired www.someAddress.com/# and I expect that my routing redirects me to www.someAddress.com/#/list or something like this. Unfortunately it doesn't happend. When I console (inside $watch) value of $state.current.name it return me empty string. I tried debugging by this, but console is still empty...
My Angular version: 1.2.28
My Ui.router version: 0.2.13
Here is plunker
The problem is, you have no ui-view.
For the ui-router to function you will need an ui-view. Replace your ng-view with ui-view and it will work.

Can you use Angular dependency injection instead of RequireJS?

I'm starting with angular, how could I break alll the code from one app into many files?, I watched the 60ish minutes intro, and they mentioned that I could do this without requirejs or any other framework.
Lets say I have something like this that works just fine:
var app = angular.module('app', []);
app.factory('ExampleFactory', function () {
var factory = {};
factory.something = function(){
/*some code*/
}
return factory;
});
app.controller ('ExampleCtrl', function($scope, ExampleFactory){
$scope.something = function(){
ExampleFactory.something();
};
});
app.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'ExampleCtrl',
templateUrl: 'views/ExampleView.html'
})
.otherwise({ redirectTo: '/' });
});
What if I wanted to have it in separate files? like this
File One:
angular.module('factoryOne', [])
.factory('ExampleFactory', function () {
var factory = {};
factory.something = function(){
/*some code*/
}
return factory;
});
File Two:
angular.module('controllerOne', ['factoryOne'])
.controller ('ExampleCtrl', function($scope,ExampleFactory){
$scope.something = function(){
ExampleFactory.something();
};
});
File Three:
angular.module('routes', ['controllerOne'])
.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'ExampleCtrl',
templateUrl: 'views/ExampleView.html'
})
.otherwise({ redirectTo: '/' });
});
File four:
var app = angular.module('app', ['routes']);
I've tried it like this and it doesn't work.
Can I do something like this and just have a script tag for File Four in the main view? or do I have to have one script tag per file?.
Thanks for the help guys.
AngularJS does not currently have a script loader as part of the framework. In order to load dependencies, you will need to use a third party loader such as RequireJS, script.js, etc.
Per the Docs(http://docs.angularjs.org/guide/module#asynchronousloading):
Asynchronous Loading
Modules are a way of managing $injector
configuration, and have nothing to do with loading of scripts into a
VM. There are existing projects which deal with script loading, which
may be used with Angular. Because modules do nothing at load time they
can be loaded into the VM in any order and thus script loaders can
take advantage of this property and parallelize the loading process.
...or, as #xanadont explained, you can add <script> tags to your page for every file.
You must have a
<script src="file.js"></script>
per each file that you're using. It should work once you have all the references in place.
Or ... check out this article for a way to roll-your-own runtime resolution of controllers.
You've got to separate the idea of downloading from the idea of loading and executing in-memory. Use Yeoman/grunt or similar build tools to manage the process of adding individual files to the project for Angular's various modules controllers, directives, services, etc. that are attached to those modules. Then, at build-time, the files will be minified and concatenated for a speed/bandwidth improvement that's vastly superior to lazy-downloading of individual files.
Once you've dealt with the files, Angular handles the rest, executing dependencies only when they're actually needed.
In the example above, #Jose, your problem was that you're not attaching your dependencies properly to the original module. You're creating new modules and burying the dependencies inside of them. In the first version, you used var app to cache the reference to the module called 'app' and then did app.controller(), etc. So, you're calling the .controller() method on the app module.
But in the second, you still need to attach those dependencies to the main app module. To do that, you need to call angular.module('app') to access the original module, then you can chain a call to .controller() or .directive() from that module, once you've retrieved it.
Bottom-line, use Angular's constructs for the loading of Angular dependencies. If, after you've gotten all of that out of the way, you still want to use Require for loading third-party scripts, go ahead. But I recommend testing first to see if you're actually adding value.

Categories