ui-boostrap $modal causes Error: [$injector:unpr] - angularjs

I'm new to angularjs and ui-bootstrap 13 and need some help.
I'm getting a unresolved from thew angularjs injector and can't figure out why.
The module definition looks like this:
var app = angular.module('MobileCOP', [
"ngRoute",
"ngTouch",
"mobile-angular-ui",
"ui.bootstrap"]);
The controller looks like this:
app.controller('CDRserver',['$rootScope','$scope','$location','serverList','$modal',
function($rootScope, $scope, $location, serverList, $modal ){
All I need to do to cause the error is inject $modal into the controller. I don't reference the modal in the code, just adding the modal service to the controller causes the issue. When the service is removed the error stops.
I'm assuming I'm missing something obvious.
Edit" As per request showing the controller assignment into the html:
.when('/cdrquery', {
templateUrl: '/MobileCOP/tmpl/CDRlist.html',
controller: 'CDRList'
})
Error:
[$injector:unpr] http://errors.angularjs.org/1.2.15/$injector/unpr?p0=%24templateRequestProvider%20%3C-%20%24templateRequest%20%3C-%20%24modal
z/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:6:450
Zb/l.$injector<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:34:1
c#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:33:83
Zb/q.$injector<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:35:57
c#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:33:83
d#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:33:300
Zb/q.$injector<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:35:75
c#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:33:83
d#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:33:300
f/<.instantiate#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:33:464
Md/this.$get</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:65:484
z/<.link#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js:7:248
J#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:52:492
h#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:46:28
ba/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:45:200
Z/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:46:431
q#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:50:162
v#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js:6:357
Wd/this.$get</h.prototype.$broadcast#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:110:279
l/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js:11:177
ve/e/l.promise.then/H#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:96:513
ve/e/l.promise.then/H#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:96:513
ve/f/<.then/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:98:173
Wd/this.$get</h.prototype.$eval#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:108:36
Wd/this.$get</h.prototype.$digest#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:105:323
Wd/this.$get</h.prototype.$apply#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:108:368
g#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:71:118
C#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:75:241
re/</y.onreadystatechange#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:76:280
<ng-view class="app-content ng-scope">
Loading scripts code:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-touch.min.js"></script>
<script src="/MobileCOP/libs/mobile-angular-ui.min.js"></script>
<script src="/MobileCOP/libs/ui-bootstrap-0.13.0.min.js"></script>
<!-- Required to use $touch, $swipe, $drag and $translate services -->
<script src="/MobileCOP/libs/mobile-angular-ui.gestures.min.js"></script>
<script src="/MobileCOP/libs/xml2json.min.js"></script>

It appears that you are not using a template enabled version of the ui-bootstrap libraries. From the ui-bootstrap FAQ:
The dist files with the -tpls- in their name come with the templates bundled inside $templateCache . You can check how this bundling works by inspecting this file. The important point here is that templates are part of the distribution file so you don't need to download them separately. Also, those templates are pre-loaded with JS file so a browser won't request them on run-time.
bottom line, for template enabled modules like modal to work, you need to be loading the script ui-bootstrap-tpls-0.13.0.js.
The error you are getting is coming from the templateRequestProvider when it looks for a template for $modal that isn't in the template cache.

OK cleared up the issue.. ui-bootstrap-tpls-0.13.0.js is incompatible with angularjs 1.2.15. Upgraded to 1.3.14, the error is gone.

Related

Angularjs template 404 not found

Using angularjs routing, sometimes I get
template/home.html Failed to load resource:
the server responded with a status of 404 (Not Found)
But I declared template/home.html inline
<script type="text/ng-template" id="template/home.html">
...template stuff...
</script>
Unexpectedly I don't get 404 every times, but sometimes.
I've already read this stackoverflow, where they remember this rule https://docs.angularjs.org/api/ng/service/$templateCache
Note: the script tag containing the template does not need to be included in the head of the document, but it must be a descendent of the $rootElement (IE, element with ng-app attribute), otherwise the template will be ignored.
I've declared my angularjs app without ng-app, but through bootstrap
angular.bootstrap(document, ['myapp']);
So my $rootElement is the document. Indeed I don't get the 404 errors every times. Is there some race conditions: sometimes $routerProvider is set before $templateCache is set with my inline template.
I'm using requirejs. Could it be the cause?
Any helps?
I think you may accidentally put your ng-template script outside of the tag where you define your main angular app.
<body ng-app="myApp">
// Your Template shuld stay here
<script type="text/ng-template" id="template/home.html">
...template stuff...
</script>
</body>

Why angular.bootstrap() to document throws error

I have my test example in this plunkr link
My question is NOT DUPLICATE of this one
Also the Google Result and Github Bug was about the bug reporter not defining the module which he was trying to bootstrap in the first place
I have 3 modules grandParentModule, parentModule and nestedModule.
I have bootstrapped parentModule and nestedModule to 2 nested div elements and they are working fine.
But as soon as I try to bootstrap grandParentModule to document, it is throwing a console error.
This is my HTML
<div id="parent" ng-app="parentModule">
<div id="nested">
</div>
</div>
And this is my SCRIPT
angular.module('grandParentModule', []);
angular.module('parentModule', []);
angular.module('nestedModule', []);
var nestedElem = document.getElementById("nested");
angular.bootstrap(angular.element(nestedElem), ['nestedModule']);
//comment / uncomment this line to toggle the error at console
angular.bootstrap(document, ['grandParentModule']);
Only this line angular.bootstrap(document, ['grandParentModule']); is causing the error
Uncaught Error: [ng:btstrpd] http://errors.angularjs.org/1.5.5/ng/btstrpd?p0=%26lt%3Bdiv%20id%3D%22parent%22%20ng-app%3D%22parentModule%22%26gt%3B
Can anyone explain to me why is it happening?
This isn't how works angular bootstrapping.
You're supposed,to bootstrap only one module.
If you use multiple independant module, the DOM element where you bootstrap them must not be nested.
Furthermore what are those module supposed to be ?
If they're linked then they must have dependencies between them ie :
angular.module('parentModule', ['grandParentModule']);
If you want to have some nested views with their own controller use either multiple ng-controller or check ui-router on the net.

Controller in separate file throws error

I am moving my controllers from one unique file containing my whole app to separate files and get that error : "Error: [ng:areq] Argument 'MainCtrl' is not a function, got undefined"
I used the setting method to define my app in app.js :
var app = angular.module('CMT', ['ui.router', 'angularCharts', 'uiSwitch']);
I then created a file MainCtrl.js with :
angular.module('CMT').controller('MainCtrl', [
'$scope', 'reviews', '$location',
function($scope, reviews, $location){
}]);
And I have included the files in index.html after including the angular source code :
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<script src='library/d3.min.js' type='text/javascript'></script>
<script src='library/angular-charts.min.js' type='text/javascript'></script>
<script src="node_modules/angular-ui-switch/angular-ui-switch.min.js"></script>
<script src="app.js" type='text/javascript'></script>
<script src="MainCtrl.js" type='text/javascript'></script>
Any hint or solution ?
Try the following:
In your app.js, inject your MainCtrl.js, like:
var app = angular.module('CMT', ['ui.router', 'angularCharts', 'uiSwitch', 'CMT.MainCtrl']);
And in your MainCtrl.js:
angular.module('CMT.MainCtrl', [])
EDIT:
An AngularJS module is a container. In every Angularjs app, you have one "main" module, and typically many sub-modules. These sub-modules are useful for modularizing/separating your app into components, like controllers, services etc. Initially you had one main module, which also contained the code for your controller. When you decided to move your controller out of the main module, what you wanted to do was move it into a sub-module.
So there were two problems with what you did:
You named your controller module (which is your sub-module in this case) the same name 'CMT' as that of your app/main module. Your sub-modules need to have unique names, and it is good practice to use the . separator - see this Angular style guide.
You didn't "link" your controller module to your app module in an Angular way. Just adding the script to your html isn't enough. If you have a sub-module called CMT.MainCtrl, you need to inject it into your main CMT module.
Judging by your naming convention MainCtrl.js versus something like controllers.js, I'm guessing you're organising your code by feature, instead of by type? In any case, read Angular best practices for more info on Angular directory structure.
Specify all your services/controllers/filters/directives files before the app.js file
<script src="MainCtrl.js" type='text/javascript'></script>
<script src="app.js" type='text/javascript'></script>
Note: you don't need to care about these file orders if you bundle all your script files into single file

How should I define the module to add controllers to it?

I've got my angular app setup something like this:
<div class="main" ng-app="myApp">
<div class="sub" ng-controller="sub1">
...
</div>
<div class="sub" ng-controller="sub2">
...
</div>
<div class="sub" ng-controller="sub3">
...
</div>
</div>
And the controllers each on different js file so the file structure is like:
Templates
-> home.html
Controllers
-> sub1Controller
-> sub2Controller
-> sub3Controller
In each controller file, I add the controller to the app by doing
ngApp.controller("sub1", function($scope){ ... });
And in the html file I linked the scripts.
After a few takes on getting the got undefined error, I found out that I am creating a new app on every directive, because to get the ngApp I used angular.module("myApp", []), unlike angular.module("myApp") that would retrieve the module. So basically my question is, where should I define the module? Since doing angular.module("myApp") won't work before angular.module("myApp", []) is invoked I can't use the one without the brackets always. Is defining the module on the containing page a bad practice? Is separating the controllers to different files instead of all in the same one a bad practice?
Separating controllers out into separate files is definitely a good idea, and I commend you for doing so. I'd recommend adding additional file above the controllers directory to define the angular module.
templates
-> home.html
js
->
angular_config.js
controllers
-> sub1Controller
-> sub2Controller
-> sub3Controller
There is nothing wrong with having all your controllers in the same file but for simplicity and future complexity reasons it is better to store each controller in a separate file.
A good solution may be to put all your controllers in controller folder(what you are currently doing )
the second thing is load another file that you can call app.js which will link all the controllers and other stuff together for example
in your app.js in the the js folder you can write :
window.onload = function(){
var app = angular.module('mymodal',[]);
app.controller('sub1Controller',function(){});
app.controller('sub2Controller',function(){});
app.controller('sub2Controller',function(){});
};
and then in your index.* file load js files in the following order
<script src="js/controllers/sub1Controller.js"></script>
<script src="js/controllers/sub2Controller.js"></script>
<script src="js/controllers/sub3Controller.js"></script>
<script src="js/app.js"></script>
By the way you can concatenate all your controllers files in one single file using task runner tools like grunt or gulp.

Why do I need to angular.bootstrap even when I declare ng-app="MyApp" in JSFiddle

I do not truly understand why it is necessary to do an angular.bootsrap document, ['MyApp'] at the end of my CoffeeScript code that manages the module and controllers in the following test application:
This is the HTML:
<div ng-app='InventoryModule' ng-controller='InventoryController'>
<ul ng-repeat='item in items'>
<li>{{item.title}}</li>
<li>{{item.price | currency}}</li>
</ul>
</div>
And the CoffeeScript:
inventoryModule = angular.module 'InventoryModule', []
inventoryModule.factory 'Items', ->
items = {}
items.query = () -> [{title: 'Hello', price: '5'}]
items
inventoryModule.controller 'InventoryController', ($scope, Items) ->
$scope.items = Items.query()
angular.bootstrap document, ["InventoryModule"]
If you remove the last line, the applicatoin won't work. Why is that? This is not truly explained anywhere else.
This is a fiddle of the code:
http://jsfiddle.net/dralexmv/8km8x/11/
As you can see the application actually works. If you remove the bootstrap it will stop working.
Tl;dr
Set the second drop-down in jsFiddle to "No wrap - in <head>" and you won't need angular.bootstrap line.
FIDDLE
Explanation
When Angular library is loaded it will scan the DOM looking for element with ng-app directive. When it finds one it will begin the bootstrapping proces.
In that process Angular will take the value of ng-app attribute (in your case that's InventoryModule) and will try to find an angular module with the same name. If it fails it will throw: Uncaught Error: No module: <module name>.
In your fiddle you have set the "Code Wrap" select box to "onLoad".
This drop-down instructs jsFiddle when to initialize the JS code that you've put in JS frame. When it's set to "onLoad", the code will run in onLoad window event.
On the other hand, Angular bootstrapping process will run on $(document).ready(), and because $().ready event is fired before "onLoad" event, Angular will try to init the InventoryModule module before the module is even defined, and that's where the dreaded "No module" error will be thrown.
angular.bootstrap() is a manual way of doing the same thing that Angular already does in it's $().ready() handler.
Take a look at the error console. Your code throws an exception:
Uncaught Error: No module: InventoryModule
I think it has something to do with it. Manually bootstrapping by calling angular.bootstrap seems to workaround the actual problem.

Resources