Angular module needs to be defined twice - javascript

I have been playing around with some angular code and I found that it has app.controllers twice on the page. Once in the module of app towards the top and once at the bottom. But when I remove one or the other the code breaks. I don't know why you need both since the app.services doesn't need that or the directives or filters. Any insights on why?
(function () {
angular
.module('app',
[
'app.controllers',
'app.services',
'app.directives',
'app.filters'
]
)
.config(['$sceDelegateProvider','$routeProvider',
function ($sceDelegateProvider, $routeProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://maps.google.com/**']);
$routeProvider
// Home
.when('/',
{
templateUrl: 'partials/home.html'
}
)
// Default
.otherwise('/');
}
]
);
angular.module('app.controllers', []);
}());

This code :
.module('app', [
'app.controllers',
'app.services',
'app.directives',
'app.filters'
]);
is creating a new module named app. Inside [] you will find the list of dependencies modules. app.controllers is one of your app dependencie.
Whereas this code :
angular.module('app.controllers', []);
is creating a new module called app.controllers with no dependencies => [] (empty array).
To summarize
To create a new module
angular.module('MODULE_NAME', []); (Note there are [])
To access the module previously created
angular.module('MODULE_NAME');
Convention name xx.yy (like app.controllers) helps to know that the module xx.yy depends of xx (app.controllers is a dependency of app)

Related

How to refactor angular dependency injection for concatination and minification?

I have written my angular application into seperate files for my readability and ways to easily find things to edit/code. This is my app.js that requires the dependencies.
app.js
var app = angular.module('app', ['ngResource', 'ngRoute', 'app.services', 'app.controllers', 'app.feed','app.directives', 'app.factories']);
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
...
}]);
This is an example of how the dependencies are written out.
services.js
var app = angular.module('app.services', []);
app.factory('AuthService', ['$scope'], function($scope) {
...
}]);
However, when I try to concat the scripts, app is redefined constantly. I thought of taking out the var declaration but, I like to keep the files separate.
How would I be able to write this out where the dependency injections stay intact for my app.js, while still keeping the files separate.
To prevent the constant re declaration of you app variable, you can take advantage of the module pattern: Angular Style Guide:Modules.
Instead of explicitly declaring app in every dependency:
var app = angular.module('app.services', []);
app.factory('AuthService', ['$scope'], function($scope) {
...
}]);
You can define you service, component, directive, controller, etc as a part of the correct module:
angular.module('app.services')
.factory('AuthService', ['$scope'], function($scope) {
...
}]);
Declaring an 'app.services' module would only need to happen once.
See : Angular Style Guide:Modules for better explanations.

module dependency with ngRoute breaks angular rendering

I am trying to use Mean stack in my website project. I am using ngRoute for routing and I want to add bootstrap carousel to my main page. I am trying to put angular team carousel component from this page.
While I am trying to implement this, I realize as soon as I try to add module dependency ( which is var app = angular.module('myApp', []) ) to my controller , angular breaks (without any error) and nothing appear in page. If I delete, everything is working normal. I assume this is related with routing ?
Project Structure;
-myApp
-node_modules
package.json
server.js
-public
-controllers
-lib
-views
app.js
index.html
app.js ;
(function(){
var app = angular.module('filmSevmem', ['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/main', {
templateUrl: 'views/main.html',
controller: 'MainController'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
})
.when('/contact', {
templateUrl: 'views/contact.html',
controller: 'ContactController'
})
.otherwise({redirectTo:'/main'});
});
})();
MainController.js;
(function(){
var app = angular.module('myApp');
var MainController = function ($scope, $http) {
....... // codes from carousel
.......
app.controller('MainController', MainController);
})();
If I add , [] or ['ngAnimate', 'ui.bootstrap'] or anything to right of 'myApp', nothing work and I get empty page from my localhost. What can cause this problem ? What should I do ? Thank you.
var app = angular.module('myApp'); means get me the module myApp.var app = angular.module('myApp', [listOfDependencies]); means create the module myApp with all of the listed dependencies. So if you put square brackets in app.js AND in mainController.js, then you overwrite the previously created. The simplest solution would be to add ngAnimate and ui.bootstrap in your app.js like this: var app = angular.module('myApp', ['ngRoute','ngAnimate','ui.bootstrap']);
If you don't want to have all your dependencies in your root module, you can make submodules like var controllers = angular.module('myApp.controllers', ['ngAnimate']), and include this in your app.js like var app = angular.module('myApp', ['myApp.controllers']);
Why you are creating two different modules? And even you are not injecting the first module while creating the second.
By no chance your application is gonna work until and unless you code everything using single module or inject one module in another!

List dependencies injected

Is there a way to know what dependencies were injected into my Angular module?
angular.module('myModule', [
'ui.bootstrap'
])
.controller('myController', [function () {
// var dependencies = Magic.dependencies;
// console.log(dependencies);
}]);
In your controller, if you inject $window, you can dig for the dependencies, specifically, there exists a .requires on your module. To do this, you can either declare your module as a global var so we can find it on our $window, in this case, let's call it app - or - you can bypass globals and $window and call angular.module('myModule').requires directly.
I've added ngRoute as well to prove the array of dependencies that will be discoverable.
var app = angular.module('myModule',
[
'ui.bootstrap',
'ngRoute'
]).controller('ctrl', ['$scope', '$window', function($scope, $window) {
console.log($window.app.requires) // ["ui.bootstrap", "ngRoute"]
console.log(angular.module('myModule').requires) // without global - $window not needed
}]);
JSFiddle Link - working example
Note - If leveraging globals, you can simply call the window as such: window.app.requires - without injecting $window. However, see the AngularJS $window docs to understand why $window is preferred.
Building on #salniro's answer, you don't need globals, or $window.
The dependencies are listed on the .requires property of angular.Module:
angular.module('myModule', [
'ui.bootstrap',
'ngRoute'
])
.controller('ctrl', function() {
var app = angular.module('myModule');
console.log(app.requires); // ["ui.bootstrap", "ngRoute"]
});
http://jsfiddle.net/8vtf6gar/1/

AngularJS - Why are dependencies with modules necessary?

Can you tell me why it is recommended to add dependency modules to the creation of a module?
I've tried to run the code without adding the modules TodoApp.controllers and TodoApp.services. Even though I removed them, everything ran perfectly .. (I call a service via those two files)
app.js
// Injects all the needed modules
var TodoApp = angular.module("TodoApp", [
"ngRoute",
"ngResource",
"TodoApp.controllers",
"TodoApp.services"
]).
config(function ($routeProvider) {
$routeProvider.
when('/', { controller: "listCtrl", templateUrl: 'list.html' }).
otherwise({ redirectTo: '/' });
});
Update
Thank you for your response! :)
Unfortunately, those files don't share a common variable:
That was actually the reason why I didn't understand the set of problem. For me, this code gets stored in nowhere. Could it be because of the dot notation in the naming?
controller.js
angular.module('TodoApp.controllers', []).
controller('listCtrl', function ($scope, $location, todoApiService) {
$scope.todos = todoApiService.getMyTodos().query();
});
services.js
angular.module('TodoApp.services', []).
factory('todoApiService', function ($resource) {
var todoApi = {};
todoApi.getMyTodos = function () {
return $resource('/api/todo/:id', { id: '#id' }, { update: { method: 'PUT' } });
};
return todoApi;
});
You do not need to inject controllers & services since they have to be part of a module anyway.
You could have them labeled like so in the other files:
TodoApp.controllers(/* ... */)
TodoApp.services(/* ... */)
They are already attaching themselves to the module because of the TodoApp variable (which in-turn is angular.module('TodoApp').
It looks like you call the module directly each time:
angular.module('TodoApp.controllers', []).
controller('listCtrl', /* etc etc */ );
Each way, you are simply adding more things (in typical dot notation) to your overall Module, and angular understand it's TodoApp since you are starting it with that.
But sometimes you'll see people inject other modules, in a way inheriting the modules controllers / directives / services / etc.
var HelperModule = angular.module('HelperModule', /*...*/);
HelperModule.directive('headerLinks', /*...*/);
HelperModule.factory('BaseFactory', /*...*/);
// etc etc
var TodoApp = angular.module("TodoApp", ["HelperModule"]); // <-- Module injected
// TodoApp now contains all the directives/etc from that module!
Hope that helps!

AngularJS seed: putting JavaScript into separate files (app.js, controllers.js, directives.js, filters.js, services.js)

I'm using the angular-seed template to structure my application. Initially I put all my JavaScript code into a single file, main.js. This file contained my module declaration, controllers, directives, filters, and services. The application works fine like this, but I'm worried about scalability and maintainability as my application becomes more complex. I noticed that the angular-seed template has separate files for each of these, so I've attempted to distribute my code from the single main.js file into each of the other files mentioned in the title to this question and found in the app/js directory of the angular-seed template.
My question is: how do I manage the dependencies to get the application to work? The existing documentation found here isn't very clear in this regard since each of the examples given shows a single JavaScript source file.
An example of what I have is:
app.js
angular.module('myApp',
['myApp.filters',
'myApp.services',
'myApp.controllers']);
controllers.js
angular.module('myApp.controllers', []).
controller('AppCtrl', [function ($scope, $http, $filter, MyService) {
$scope.myService = MyService; // found in services.js
// other functions...
}
]);
filters.js
angular.module('myApp.filters', []).
filter('myFilter', [function (MyService) {
return function(value) {
if (MyService.data) { // test to ensure service is loaded
for (var i = 0; i < MyService.data.length; i++) {
// code to return appropriate value from MyService
}
}
}
}]
);
services.js
angular.module('myApp.services', []).
factory('MyService', function($http) {
var MyService = {};
$http.get('resources/data.json').success(function(response) {
MyService.data = response;
});
return MyService;
}
);
main.js
/* This is the single file I want to separate into the others */
var myApp = angular.module('myApp'), []);
myApp.factory('MyService', function($http) {
// same code as in services.js
}
myApp.filter('myFilter', function(MyService) {
// same code as in filters.js
}
function AppCtrl ($scope, $http, $filter, MyService) {
// same code as in app.js
}
How do I manage the dependencies?
The problem is caused from you "redeclaring" your application module in all your separate files.
This is what the app module declaration (not sure declaration is the right term) looks like:
angular.module('myApp', []).controller( //...
This is what assignment (not sure if assignment is the right term either) to your application module looks like:
angular.module('myApp').controller( //...
Notice the lack of square brackets.
So, the former version, one with the square brackets, should only be used once, usually in your app.js or main.js. All other associated files — controllers, directives, filters … — should use the latter version, the one without the square brackets.
I hope that makes sense. Cheers!
If you're wanting to put your different parts of your application (filters, services, controllers) in different physical files, there are two things you have to do:
Declare those namespaces (for lack of a better term) in your app.js or in each file;
Refer to those namespaces in each of the files.
So, your app.js would look like this:
angular.module('myApp', ['external-dependency-1', 'myApp.services', 'myApp.controllers'])
.run(function() {
//...
})
.config(function() {
//...
});
And in each individual file:
services.js
angular.module('myApp.services', []); //instantiates
angular.module('myApp.services') //gets
.factory('MyService', function() {
return {};
});
controllers.js
angular.module('myApp.controllers', []); //instantiates
angular.module('myApp.controllers') //gets
.controller('MyCtrl', function($scope) {
//snip...
})
.controller('AccountCtrl', function($scope) {
//snip...
});
All of this can be combined into one call:
controllers.js
angular.module('myApp.controllers', [])
.controller('MyCtrl', function($scope) {
//snip...
});
The important part is that you shouldn't redefine angular.module('myApp'); that would cause it to be overwritten when you instantiate your controllers, probably not what you want.
You get the error because you didn't define myApp.services yet. What I did so far is putting all the initial definitions in one file and then use them in another. Like for your example I would put in:
app.js
angular.module('myApp.services', []);
angular.module('myApp',
['myApp.services',
...]);
That should get rid of the error, though I think you should have a read on the article Eduard Gamonal mentioned in one of the comments.

Categories

Resources