I'm new to Angular and am working through various tutorials (Codecademy, thinkster.io and so on) and have seen two ways of declaring the app container. Firstly:
var app = angular.module('myApp', [])
Or simply like this:
angular.module('myApp', [])
Is one better practice over the other or is it simply a different style without any major effect?
There'n no difference in how both the approach works except following
var app = angular.module('myApp', []) will add an extra global variable(If you're hyper conscious about global variables), however this will shorten your code, don't have to repeat angular.module('myApp') multiple times. You can use app instead of angular.module('myApp').xxx at many times.
You can chain the methods as follow, instead of adding a variable
angular.module('myApp', [])
.controller(.....)
.directive(.....)
.factory(.....);
angular.module supports a third parameter, config function. If you chain you can do more than one config, which may be useful if you have a lot of configurations.
angular.module('myModule', [])
.config(function(injectables) {
//config block 1
})
.config(function(injectables) {
//config block 2
});
Instead of:
angular.module('myModule', [], function(){
//only config
});
Also it eliminates risk of creating global variables when creating providers.
There is no difference, only the style and whatever you prefer, see this
angular.module('myApp', [])
.controller("xCtrl", ['$scope', function($scope){
}])
.controller("yCtrl", ['$scope', function($scope){
}])
.controller("zCtrl", ['$scope', function($scope){
}]);
In this case if you put the ; after y controll, z controller will not work. Means all will be treated as a single function. On the other way:
var app = angular.module('myApp', []);
app.controller("xCtrl", ['$scope', function($scope){
}]);
app.controller("yCtrl", ['$scope', function($scope){
}]);
app.controller("zCtrl", ['$scope', function($scope){
}]);
In it every function is independent.
The only reason for setting a global variable referring to your module, is if you want to separate it in to multiple files.
for example:
main.js:
var app = angular.module('myApp', [])
.controller('controller1',.....)
.controller('controller2',.....);
directives.js
app
.directive('directive1',.....)
.directive('directive2',.....);
although,you should know it is not so good to relay on global variables (app is global in this example), because they could get overridden by other librarys, and there are other ways to refer to your module in other files, like in this example:
main.js:
angular.module('myApp', [])
.controller('controller1',.....)
.controller('controller2',.....);
directives.js
angular.module('myApp')
.directive('directive1',.....)
.directive('directive2',.....);
and if it is a big and complex angular application, you might even want to separate it to multiple modules:
main.js:
angular.module('myApp', ['myApp.directives'])
.controller('controller1',.....)
.controller('controller2',.....);
directives.js
angular.module('myApp.directives', [])
.directive('directive1',.....)
.directive('directive2',.....);
Related
I have the following code:
main.js
angular.controller('myCtrl', function($scope, $rootScope) {
$scope.name = "Bob";
}
myservices.js
angular.factory('myService', function($http) {
var myService = {
async: function(params) {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get("http://myws/user/info/"+params).then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
How can inject myService in myCtrl ? considering they are in two separated files.
We need to add in order all of our scripts we have created to run this angular, take note the order:
<script src="angular.js"></script>
<script src="main.js"></script>
<script src="myservices.js"></script>
main.js should look like:
var app = angular.module("MyModule", []);
app.controller('myCtrl', function($scope, $rootScope, myService) { /* implementation */})
services.js should look like:
app.factory('myService', function($http) { /* implementation */});
So in our main.js we are creating a module to attach all of our services, factories, providers, values, constants, controllers and directives. It also allows us to put the config and run phase functions in.
The module is instantiated via:
angular.module("MyModule", []);
We're providing a second argument of other dependant modules
If we needed to, we could ask angular for the module again, in the case of use javascript modules:
var app = angular.module("MyModule");
Below are several thing you need to do.
Should be they should belong same/different angular module(if its different module then you have inject into main module to use it).
You need to use angular.module('myApp') to bind components to it, so that the service will be available in that module.
Code
//app.js
angular.module('myApp', ['myApp.service']); //this should be module definition somewhere
//service.js
angular.module('myApp.service', [])
angular.module('myApp.service').factory('myService', function($http) {
//service code
});
//controller.js
angular.module('myApp').controller('myCtrl', function($scope, $rootScope, myService) {
console.log(myService); //service instance here
$scope.name = "Bob";
}
you can inject service in your controller
like:
main.js:
angular.module('myApp', []).controller('myController', ['$scope', 'myService',
function ($scope, myService) {
}
]);
myService.js:
angular.module('myApp').factory('myService', function($http) {
//service code
});
for different file but same module then ensure that file is loaded before use.
Make sure the files are both actually loaded. How to do that is up to you, perhaps you're using some implementation of require(), or you simply list all the files in your HTML as <script> tags.
Clarify what module structure you want to have. Should both be part of the same module, or should they be separate modules?
Same module: One file needs to declare the module, the other needs to extend it:
angular.module('Foo', []) // declares new module
.controller(..)
angular.module('Foo') // extends existing module
.factory(..)
Different modules:
angular.module('Foo', []) // declares new module
.factory(..)
angular.module('Bar', ['Foo']) // declares new module
.controller(..) // and imports other module
Inject into the controller:
.controller('myCtrl', function ($scope, myService) ..
This is more of an architectural question.
One of the most common forms of defining an angular module is this:
angular.module('app', [])
.controller('Ctrl', ['$scope', function Ctrl($scope) {
//body...
}]);
But I don't find the syntax very intuitive. How about having the list of dependencies in an array like AMD:
angular.module('app', [])
.controller('Ctrl', ['$scope'],
function Ctrl($scope) {
//body...
});
This way the whole array will contain only string elements each of which refers to a module. The array matches the function parameters one by one. (kinda like arguments).
So my question is why Angular designers went for this convention?
It kind of does that in a sense. you can do this by using $inject.
function SomeCtrl ($scope) {
// do something with $scope
}
SomeCtrl.$inject = ['$scope'];
angular
.module('app', [])
.controller('SomeCtrl', SomeCtrl);
I am not a no Expert on this, but I did found a great post on how this process works and it might help answer your question: http://toddmotto.com/angular-js-dependency-injection-annotation-process/
Im trying to separate my Angular controllers into different files. Right now each one appears like this.
AddPropertyController.js
angular.module('myApp.controllers.addproperty', [])
.controller(...);
SearchController
angular.module('myApp.controllers.search', [])
.controller(...);
Now for each one of these I had to include them in the Angular myApp. via:
angular.module('myApp', [
'myApp.controllers.search',
'myApp.controllers.addproperty'
])
my question is, is there a way to just include them all at once instead of adding them individually? My first attempt was to name each module the same, angular.module('myApp.controllers',...) then just include myApp.controllers in the App. But that didn't seem to work... I guess Im asking is what is the best way to have separated controller files but in all in one module. Thanks for the help!
Check out the angularjs docs for info on controllers and adding them to app level modules...
For example for your code:
var myApp = angular.module('myApp',[]);
myApp.controller('SearchController', ['$scope', function($scope) {
$scope.search = 'Hola!';
}]);
myApp.controller('AddPropertiesController', ['$scope', function($scope) {
$scope.props = [];
}]);
You're basically attaching each controller to the myApp instance, so the app is aware of the controllers.
I would organize them like this:
MyController1.js
var MyController1 = ['$scope', function($scope) {
}];
MyController2.js
var MyController2 = ['$scope', function($scope) {
}];
MyModule.js
var app = angular.module('MyModule',[]);
app.controller({
MyController1: MyController1,
MyController2: MyController2,
etc
});
This is the similar to how the Angular source code is itself organized:
AngularPublic.js
ng Directives
I am getting started with AngularJS, and as I understand, I can have different controllers for different sections of my web page. I am having the problem getting it work. I have two sections of my page and corresponding to each one ng-controller - JSFiddle. Only the section that come first works. For example currently, app1 works fine, but when I move it below app2, only app2 works fine. What could be wrong? Much appreciate any explanation regarding why this behavior and any links.
You can have multiple controllers, but you cannot have multiple ng-app directives on the same page. This means you should only have a single ng-app directive in your html that points to a single module that will be used in your application.
You then define this module and define all your controllers in this module:
var app = angular.module('app', []);
app.controller('TextController', function ($scope) {
//Controller Code Here
});
app.controller('ItemController', function ($scope) {
//Controller Code Here
});
If for some reason you want to have controllers in separate modules, you can still do that, and include those modules as dependencies of your main module:
var items = angular.module('items', []);
var text = angular.module('text', []);
var app = angular.module('app', ['items', 'text']);
text.controller('TextController', function ($scope) {
//Controller Code Here
});
items.controller('ItemController', function ($scope) {
//Controller Code Here
});
Generally you don't need to have a module for each controller. Modules are used to group related pieces of functionality together to make it easy to take that and re-use it in another application.
Here are links to some examples:
Single Module : http://jsfiddle.net/36s7q/4/
Multiple Modules: http://jsfiddle.net/36s7q/5/
Notice how in both example there is only a single ng-app on the page.
Take a look at this, I changed a lot around. http://jsfiddle.net/36s7q/6/
No need for two app modules on the page to achieve two controllers, you can have multiple controllers within the same module. I also simplified the syntax. Take a look.
var items = angular
.module('app1', [])
.controller('ItemController', function($scope) {
$scope.items = [ {
title : 'Pencil',
quantity : 8,
price : 4.2
}, {
title : 'Pen',
quantity : 2,
price : 5.2
}, {
title : 'Watch',
quantity : 3,
price : 10.2
} ];
})
.controller('TextController', function($scope) {
$scope.text = {
message : 'Welcome!!'
};
});
Here is how you have multiple controllers:
var app = angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache']);
app.controller('DemoCtrla', DemoCa)
.controller('DemoCtrlb', DemoCb)
.controller('DemoCtrlc', DemoCc);
function DemoCa($mdConstant) {
// function here
}
function DemoCb($mdConstant) {
// function here
}
function DemoCc($mdConstant) {
// function here
}
I hope it helps ;)
Instead of answering your actual question, i suggest usage of routing.
Be aware: This technique is not needed to solve your issues. However, you may want to know about it for future projects.
If i got you right, all you want to do is using a different controller / view for a specific section of your page.
To achieve this, create a single application module (remember, Angular applications are SPA's). Then, you could define some routes and tell Angular what to use when one of them is demanded:
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {templateUrl: './partials/views/root.html', controller: 'rootCtrl'}}).
when('/section', {templateUrl: './partials/views/section.html', controller: 'sectionCtrl'}}).
otherwise({redirectTo: '/'});
}]);
Further reading: http://docs.angularjs.org/api/ngRoute
Be aware that the latest stable version of Angular requires the ngRoute module in order to use the routeProvider.
I wonder why I can't access a factory within the same module.
As I think it is better to build a web app with different independent modules, I would like to group all methods (services, factories, directives, ...) within the same module.
What do I do wrong?
app = angular.module("MyGreatModuleProvider", []);
app.factory("MyFactory", function($rootScope, $scope) {
return {
myFunction: function() {
console.log("Hello World");
}
}
});
app.controller("myCtrl", function($scope, MyFactory) {
MyFactory.myFunction();
// This doesnt't work, unknown provider
});
Factories don't have a $scope
If you remove the $scope and only keep the $rootScope it works just fine
You can remove both $scope and $rootScope from the factory declaration. Here's a plunker.
Define your injected object names to let the Angular know what to inject into fields:
app.controller("myCtrl", ['$scope', 'MyFactory', function($scope, MyFactory) {
MyFactory.myFunction();
}]);
It's a good practice especially if you are going to compile your application.
Moreover as others pointed out: factories doesn't have $rootScope and $scope.