Initialize ng-admin module in a callback function - angularjs

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.

Related

AngularJs dependency not working

I've just installed the following package with bower:
https://github.com/urish/angular-spinner
The package is added successfully. I've also added:
<script src="bower_components/spin.js/spin.js"></script>
<script src="bower_components/angular-spinner/angular-spinner.js"></script>
When I try to inject it like this:
(function()
{
angular.module('employeeApp',['angularSpinner']).controller('schoolController', schoolController);
It crashes and I receive the error:
Argument 'indexController' is not a function, got undefined
When I remove ['angularSpinner'] everything works again.
What should I do?
--EDIT--
indexController
angular.module('employeeApp').controller('indexController', indexController);
function indexController($location, authenticationFactory,constants)
{
var vm = this;
vm.setName = function()
{
return constants.firstname;
}
}
in angular you create module for your app and there you specify the dependencies. and once you create controller or service you get the module by name and create controller\ service in that module.
//create module for app
angular.module('employeeApp', [ /*add your dependencies here*/ ]);
//create controller\ service
angular.module('employeeApp').controller(function(){
//controller implementation
});
what might happen is you may re initialize your app by mistake.
for simplification you could store your angular module in a variable as follows:
var app = angular.module('employeeApp', ['angularSpinner']);
and define a controller like this:
app.controller('indexController',function(angularSpinner){
//controller code here
});

Error in registering the controller AngularJS

My code is like this
App.js
angular.module('mailerApp', [
'mailerApp.services',
'mailerApp.controllers',
'ui.bootstrap',
'angular-loading-bar',
'textAngular',
'angularFileUpload'
]);
Cotrollers.js
angular.module('mailerApp.controllers').controller('MailerCntrl', ['$scope', 'FileUploader', function ($scope, FileUploader) {
}]);
Services.JS
angular.module('mailerApp.services', []).factory('rateRequestService', ['$http', rateRequestService]);
function rateRequestService($http) {
var service = { getData: getData };
return service;
function getData() {
return $http({
method: 'Get',
url: '../services/RateRequestWS.asmx/GetReadOnlyData?'
});
}
}
HTML
body ng-app="mailerApp" ng-controller="MailerCntrl">
</body>
Everything looks okay to me, But this throws an error
Uncaught Error: [$injector:nomod] Module 'mailerApp.controllers' 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.
Can any one point out What I am doing wrong here?
Instead of
angular.module('mailerApp.controllers').controller...
You need to do
angular.module('mailerApp').controller... // to add the controller to the mailerApp module
angular.module('mailerApp.controllers', []).controller... // to add the controller to a new mailerApp.controllers module
And the same goes with;
angular.module('mailerApp.services').factory...
Instead you need to
angular.module('mailerApp').factory... // add the factory to the mailerApp module
angular.module('mailerApp.services', []).factory... // add the factory to a new mailerApp.services module
When you create and angular module, you give it a name and the list of dependencies in the array;
var module = angular.module('<module_name>', [<dependencies>])
But then when you add a controller/factory to the module, you'll need to either use the module object you created.
when you write angular.module('mailerApp.controllers', [ ]), you create new module as 'mailerApp.controllers' and in second parameter you pass dependencies.
and when you write angular.module('mailerApp.controllers') it references previously created module.
But in your case your directly referencing module without creating it, therefore it gives you error for that. Same goes for other cases

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.

Angularjs manual bootstrap

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/

How to update directive using data from service?

Assuming I have a service MyService that has a property "data" that contains contents retrieved from 2 or 3 $http requests and stores it into "data". This "data" needs to be accessible or passed to a directive to process, (like a modal).
The service "MyService" contains an attribute "data" necessary for myDirective to process on first load.
// var app = angular.module...
app.service('MyService',...)
I have a separate directive "myDirective":
var myDirective = angular.module('myDirective', []);
myDirective.directive('control', ['Params', function(Params) {...
I tried to inject "MyService" by doing the following:
var myDirective = angular.module('myDirective', ['MyService']);
myDirective.directive('control', ['Params', function(Params) {...
Though it fails to instantiate saying:
error: [$injector:nomod] Module 'MyService' 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.
How do I properly instantiate my myDirective from myService? Is this the right approach or should I be using some controller/factory/provider?
You are treating myService as a module which it is not, it is a component of a module. You only inject modules into other modules. Once all dependent modules are injected into main module, components of all modules are directly available to other components, regardless of which module they are initially registered to.
To inject into a directive you do it the same way you are injecting Params into directive. I suspect you are needlessly creating a new module just to create a directive.
Try this way:
app.service('MyService',...);
app.directive('control', ['Params','MySerrvice', function(Params,MyService) {...
Now within the directive you have access to objects in service using MyService.propertyName
What you are trying is adding MyService service as a module to your MyDirective module which won't work.
The easy way would be to just add the directive to your app module and inject your service:
app.directive('control', ['Params', 'MyService', function(Params, MyService) {
//...
}]);
If you create extra modules for your directives and and maybe also for your services you will have to add these modules to your app module like for example (usually in app.js):
var directivesModule = angular.module('app.directives', []);
var servicesModule = angular.module('app.services', []);
var app = angular.module('app', ['app.directives', 'app.services']);
And then add your services and directives to the respective modules:
servicesModule.service('MyService',...);
directivesModule.directive('control', ['Params','MyService', function(Params, MyService) {
//...
}]);
Create one file per service/directive or a file for all services and one for all directives. Depends on the size of your app.

Resources