Angularjs manual bootstrap - angularjs

I would like to manually bootstrap my angular app on dom load but Angular doesn't seem to be able to bootstrap my app when i try to wait until dom load
<body>
<div ng-app="myApp">
{{1 + 1}}
</div>
<script src="angular.js"></script>
<script type="text/javascript" src="delay.js"></script>
</body>
And here's delay.js
window.onload = function(){
console.log('reached 2')
var myApp = angular.module('myApp',[])
}
console.log('reached 1')
The above code throws with the following error.
reached 1
Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:nomod] Module 'myApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify th...<omitted>...0)
reached 2
After looking at various other examples, the bootstrapping seems to work seamlessly when i do it outside the window.onload event like this.
delay.js
//this bootstrap works
angular.module('myApp',[])
console.log('reached 1')
Not sure what's happening here, is the module not visible to angular during the onload callback ?
Further even the following in delay.js fails
//still fails to bootstrap
angular.element(document).ready(function(){
console.log('reached 2')
var myApp = angular.module('myApp',[])
})
Even the following fails to work
angular.element(document).ready(function(){
console.log('reached 2')
angular.bootstrap(document,[myApp])
var myApp = angular.module('myApp',[])
})
OR
angular.element(document).ready(function(){
console.log('reached 2')
var myApp = angular.module('myApp',[])
angular.bootstrap(document,[myApp])
})
OR even
angular.element(document).ready(function(){
angular.bootstrap(document.body.children[0],['myApp'])
var myApp = angular.module('myApp',[])
console.log('reached 2')
})

AngularJS bootstraps itself automatically on DOMContentLoaded. This event fires as soon as the DOM is ready. That means you don't have to manually bootstrap your app if all you need is the DOM being ready.
The window.onload event however waits for all content to be loaded. That includes all scripts, images and other resources.
In case you still want to manually bootstrap on ready, this is how you do it:
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
angular.bootstrap will create the app for you on the element specified. In this case on document. This means you don't need to have the ng-app directive if you manually bootstrap your app. (Please note that I first incorrectly assumed that you still need it.)
You can not have your module declaration inside your ready callback, because as stated in the developer guide:
"Notice that angular.bootstrap will not create modules on the fly. You
must create any custom modules before you pass them as a parameter."
Here is a corrected fiddle that shows that ng-app isn't needed when manually bootstrapping: http://jsfiddle.net/Yxaba/

Related

Check $scope variable with jasmine return error

Currently trying to check very simple angular variables and functions. I cannot get even the simplest to work. This is my first time using it, and I need to use the older version as my lecturer requires it.
In the app.js I have many controllers but im only starting with one controller, with one variable assigned to a string:
var app = angular.module('myApp', ['ngRoute']);
blah blah blah etc etc
app.controller('HomeController', function ($scope) {
$scope.name = 'Batman';
}
In the runner.html file I have the following:
<script src="lib/jasmine-2.2.0/jasmine.js"></script>
<script src="lib/jasmine-2.2.0/jasmine-html.js"></script>
<script src="lib/jasmine-2.2.0/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src='https://code.angularjs.org/1.4.8/angular-mocks.js'></script>
<!-- include source files here... -->
<script src="../js/main.js"></script>
<!-- include spec files here... -->
<script src="spec/test.js"></script>
In the test.js i have the following:
describe('myApp', function () {
var scope, controller;
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.inject(function($controller,$rootScope){
scope = $rootScope.$new();
$controller('HomeController', {$scope: scope});
}));
it('sets the name', function () {
expect(scope.name).toBe('Batman');
});
});
I then get the following error when I run the test:
Error: [$injector:modulerr]
EDIT
It appears to be the angular routing causing the problem. When I removed the route module 'ngRoute' it appears to function correctly. Is there is method to using jasmine with routing?
The problem with this was you were not having angular-route library included despite having it as a module dependency (angular.module('myApp', ['ngRoute'])).
I added as the following along with other libraries:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular-route.min.js"></script>
And it's working!
Here's working plunker

How to bootstrap another angularjs app after the other?

Does anybody have an idea how to create an angularjs app with modules loginApp and mainApp, login will use login.html and mainApp will use index.html?
Below is the scenario I want to achieve.
Run loginApp
Once authenticated, run mainApp
I am currently doing the above scenario since I want my login page to load faster, so instead of using index.html which has lots of <script> included.
Angular app initialization manually.
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
More information Bootstrap Angular App
You can manually bootstrap app. see here [more][1]
Manually Bootstrapping an AngularJS Application
Let's start by defining our application's main module:
var myApplication = angular.module("myApplication", []);
Now, instead of relying on the ng-app attribute, we can call the angular.bootstrap function manually. We need to hand it both the application root and the name of our main module. Here's how you call it as soon as the DOM has finished loading:
angular.element(document).ready(function() {
angular.bootstrap(document, ["myApplication"]);
});
Only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. AngularJS applications cannot be nested within each other. -- http://docs.angularjs.org/api/ng.directive:ngApp
See also
https://groups.google.com/d/msg/angular/lhbrIG5aBX4/4hYnzq2eGZwJ
http://docs.angularjs.org/api/angular.bootstrap

Initialize ng-admin module in a callback function

I'm trying to configure an ng-admin app. I'd like to load some data from a file before starting the configuration, however when I try to do this in a callback I get the following error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module adminModule due to:
Error: [$injector:nomod] Module 'adminModule' 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.
Here's the code:
$.get('/api/schema', function buildNgConfig(data) {
var adminModule = angular.module('adminModule', ['ng-admin']);
adminModule.config(['NgAdminConfigurationProvider', function (nga) {
var app = nga.application(data.label).baseApiUrl('/api/');
// ...
If I take the adminModule.config out of the ajax load callback (and use data embedded in the page so I don't need a callback) and put everything in the global scope, it works.
Is there something I need to do if I want to initialize the angular module in a function?
Okay, got this sorted out with some help from a friend. The error is a result of Angular's automatic initialization happening before your module has been created. Having:
<body ng-app="myApp">
<div ui-view></div>
in your HTML tells Angular to initialize itself immediately. Deferring initialization in a callback means your Angular module won't exist and Angular's attempt to initialize it will fail.
Angular's bootstrap process is documented here, along with instructions on how to defer initialization.
To make it work with ng-admin, remove the ng-app from the body:
<body>
<div ui-view></div>
Then in your app js, you can defer initialization. For example:
angular.element(document).ready(function() {
var myApp = angular.module('myApp', ['ng-admin']);
myApp.config(['NgAdminConfigurationProvider', function (nga) {
var app = nga.application('My App').baseApiUrl('/api/');
var someEntity = nga.entity(...
// add entities
nga.configure(app);
}]);
// Now we can manually boostrap
angular.bootstrap(document, ['myApp']);
});
This waits for page load rather than executing immediately, and everything is in the callback scope rather than global.

Argument 'fn' is not a function, when trying to do unit test with Jasmine and AngularJS

I'm trying to do some unit tests with Jasmine in my Angular application, but I'm facing some errors.
Error
Error: [$injector:modulerr] Failed to instantiate module LocalStorageModule due to:
Error: [ng:areq] Argument 'fn' is not a function, got string
Spec
describe("testing the controller", function () {
var $controllerConstructor;
var scope;
beforeEach(module('app', ['ngRoute', 'LocalStorageModule']));
beforeEach(inject(function ($controller, $rootScope) {
$controllerConstructor = $controller;
scope = $rootScope.$new();
}));
it("should validate a contact", function () {
var ctrl = $controllerConstructor('crmContatosCtrl', { $scope: scope });
});
});
App.js
angular
.module('app', ['ngRoute', 'LocalStorageModule'])
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
// My routeProvider here
}]);
I'm not using neither Yeoman nor Karma yet, because this is my fisrt application using Angular.
Included Files
<script src="../../Scripts/jasmine/jasmine.js"></script>
<script src="../../Scripts/jasmine/jasmine-html.js"></script>
<script src="../../Scripts/jasmine/boot.js"></script>
<script src="../../Scripts/angular/angular.js"></script>
<script src="../../Scripts/angular/angular-mocks.js"></script>
<script src="../../Scripts/angular/angular-route.js"></script>
<script src="../../Scripts/angular/angular-local-storage.js"></script>
<script src="../../Scripts/ngStorage.js"></script>
<script src="../../Scripts/ng-infinite-scroll.js"></script>
<script src="../../Scripts/angular/common.js"></script>
<link href="../../Scripts/jasmine/jasmine.css" rel="stylesheet" />
<script src="../core/app.js"></script>
<script src="../crm/contatos.js"></script>
<script src="contatosSpec.js"></script>
I think you may simply have a problem with your configuration for the dependencies for the tests. Without Karma I don't know how you do the tests but I guess you have somewhere a configuration file for Jasmine where you specify the files to be included. You have to include all files and you have to include first all the libraries. Be careful with the order and try to respect the same as you have in your html file that you use to run the application.
If the order is wrong the JS will try to execute before the libraries it needs are included. In your case maybe even the whole angular stack.
Update
Do not forget that Jasmine works using it's own html file and will not include the libraries you usually use if you do not tell it. And also don't forget to include Angular Mock library , essential for your tests
Update 2
Ok I think I found why you have a problem
There is something wrong in this code
beforeEach(module('app', ['ngRoute', 'LocalStorageModule']));
In angular when you call a module using module('smthg',[]) you are creating it, not calling it. You should use this form instead, there is no need to reimport the services that you already included in your main module.
beforeEach(module('app'));
check the Creating versus Retrieval section of the angular documentation https://docs.angularjs.org/guide/module

Why should retrieved module name should be same as the module name passed in the first argument in angular.module

I have written a program which uses angular modules.
I have created a module as follows:
// Module A
var modA = angular.module("moduleA",[]);
//Controller A
modA.controller("AController", function($scope, $rootScope, $log){
$log.info("In controller A");
$scope.message = "I am in controller A";
});
Created some another module and controller.
Created a new angular module using above created modules as :
var myApp = angular.module("mainModule",["modA","moduleB"]);
But when I run the code, I am getting the following error:
Uncaught Error: No module: modA
But when I change the retrived module name "modA" to "moduleA" which is passed as first argument in module in while creating it works. May I know the reason/explanation why it is so?
The full code is as follows:
<!DOCTYPE HTML>
<html ng-app="mainModule">
<head>
<script type="text/javascript" src="../js/angular.js"></script>
<script text="text/javascript">
// Module A
var modA = angular.module("moduleA",[]);
//Controller A
modA.controller("AController", function($scope, $rootScope, $log){
$log.info("In controller A");
$scope.message = "I am in controller A";
});
// Module B
var moduleB = angular.module("moduleB",[]);
// Controller B
moduleB.controller("BController", function($scope, $rootScope, $log){
$log.info("In controller B");
$scope.message = "I am in controller B";
});
var myApp = angular.module("mainModule",["modA","moduleB"]);
</script>
</head>
<body>
<div ng-controller="AController">
<span>{{message}}</span>
</div>
<div ng-controller="BController">
<span>{{message}}</span>
</div>
</body>
</html>
A module is a collection of configuration and run blocks which get applied to the application during the bootstrap process.
Modules can list other modules as their dependencies. Depending on a module implies that required module needs to be loaded before the requiring module is loaded.
In your case you are injecting "modA"
var myApp = angular.module("mainModule",["modA","moduleB"]);
which is not declared before hence cannot be loaded.
Due to which it throws an error during "Dependency Injection".
This is happening during Asynchronous loading mechanism of VM to execute modules, 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.
You may refer to link for further info.
Angular's error is during Dependency Injection. The injector uses the module/component names you specify:
var modA = angular.module("moduleA",[]);
In that case you are telling it to create a module named "moduleA" with the dependencies of no other module. It doesn't care what you named the variable, it simply registers it by the name you give. In fact, you don't even need to store the return value because you can chain it or retrieve it
angular.module('moduleA').controller('MyOtherCtrl', function()...);
When you call angular.module(name) with no second argument it retrieves the module by name so you can add components to it that way as well.

Resources