AngularJS Module - javascript

I am new in AngularJS.I am learning AngularJS. I found below syntax.
var app = angular.module('myApp', ['ngRoute']);
Here is my question is What does it mean by [ ] this square bracket ??
What are functionalities/responsibilities of myApp and ngRoute ?? What are they doing here ??
Which options are available to use like ngRoute ??
I searched a lot in Google. I got several sample code. But could not get any explanation regarding all these things.
Thnanks

As per the angular module developer guide found here: https://docs.angularjs.org/guide/module
<div ng-app="myApp">
<div>
{{ 'World' | greet }}
</div>
</div>
var myAppModule = angular.module('myApp', []);
The reference to myApp module in <div ng-app="myApp">. This is what bootstraps the app using your module.
The empty array in angular.module('myApp', []). This array is the list of modules myApp depends on.
I suggest you read the official documentation as well: https://docs.angularjs.org/api/ng/function/angular.module

Basically [ ] means the module list, your module depends on.
Suppose you write a angular module myApp that depends on ngRoute that is an another angular module.
The benefits of that you can inject lots of third party angular module that works on different different area. So you dont have to reinvent the wheel. By injecting ngRoute you can easily get the functionality of routing in your app.
I think the description I write helps you to understand clearly

In javascript, you can define a array like this:
var arr = [];
the [] here is the same as the [] around 'ngRoute', that means the second parameter of angular.module() method is a array.
you can define a module like this as well:
var app = angular.module('awesomeApp', ['ngRoute', 'ngAnimate', 'ngXXX']);
the first param 'awesomeApp' is the name of your module, the second param [ngRoute', 'ngAnimate', 'ngXXX'] is the dependencies of your module.
Here the dependency will provide some interfaces or features or functions or any stuff that will help you to make your module work as your expectation.

What you pass as the second arguments is the list of your dependencies.
In a basic app, is would be just an empty array.
var app = angular.module('myApp', []);
Basically it could be anything, from the 3rd party plugins that you download to other plugins that you yourself wrote to use. You can find plenty plugins here: http://ngmodules.org/
I'd suggest you to read the angular official documents.

This syntax defines a module.
var app = angular.module('myApp', ['ngRoute']);
myApp this is the name of the app, this is just a string.
[ngRoute] within the square brackets are the modules you'd like to inject (the notion of dependency injection). Some common ones you might have seen or will see include ui.bootstrap, restangular, ui.select etc.
Two things worth mentioning:
Please be careful to not mix it up with the module referencing syntax (without the square brackets):
Module definition
angular.module('myApp', []);
Module referencing
angular.module('myApp');
Usually, it's better practice to simply write the module definition out instead of assigning it to a variable, as in
Module definition
angular.module('myApp', []);
instead of
var app = angular.module('myApp', ['ngRoute']);
You can have a look at Papa John's style guide for more information.
https://github.com/johnpapa/angular-styleguide
Hope this helps. :)

Related

Does Angular DI work at both Module and Controller level?

There are plenty of examples describing how DI operates at controller level in Angular.js but I am new to Angular and I am looking at the code of creating a new module and when I look at following code:
var app = angular.module("myApp", []);
When it says that if this module is using other modules then we can specify them in in []. Is is also not a kind of Dependency injection?
So would it be correct statement to say that DI works at both Module and Controller level in Angular.JS?
Yes, DI works at both Module and Controller level.
But, the difference is
var app = angular.module("myApp", []);
in the above line you inject modules that myApp module depends upon.
Whereas, at controller level, you inject services.
var app = angular.module("myApp", ['navigation']);
app.controller("appController", function(navDataService){
});
So, when AngularJS bootstrap application, it look at module dependencies and load those modules and make the services available, so that, they can be injected into contoller.

Meaning of the empty array in angularJS module declaration

In my previous question, I understand that the code var app = angular.module('myApp', []); connects the module app to the view myApp.
I would like to know why we are having the empty array [] in the module declaration.
What is the empty array used for?
angular.module('app', []) is to create a new module without any module dependency.
angular.module('app') is to retrieve an existing module whose name is app.
That array is meant to add various module to your current app which
is mentioned in your first part of angular.module as string`, You could simply
say for injecting various dependency.
You could create an n number of module inside your app for each component of angular & then you could combine them into one single app and you can angular.bootstrap or apply it on page using ng-app directive.
Example
Suppose you have an app which has different component like services, factory, filters, directives, etc. You could create a module for each of them. Just for making separation of concern.
angular.module('myApp.filters', [])
angular.module('myApp.services', [])
angular.module('myApp.controllers', [])
angular.module('myApp.directives', [])
angular.module('myApp.constants', [])
And while appending an component to it you could simply use that specific module of it. Like you wanted to add service then you just add that service into myApp.services by doing
angular.module('myApp.services').service('example', function(){
})
And then inside you app.js you could do combine all of this modules to an single module like below.
angular.module('myApp', [
'myApp.services',
'myApp.controllers',
'myApp.directives',
'myApp.directives',
'myApp.constants'
])
While initializing an app you could simply use myApp inside, that would make available all other module to it.
What is the empty array used for?
In you code you are creating an module which doesn't inject any dependency, [] which means it is independent of any other angular module.
Dependency injected inside the [] is nothing but importing module
Angulars API says Passing one argument retrieves an existing angular.Module, whereas passing more than one argument creates a new angular.Module
https://docs.angularjs.org/api/ng/function/angular.module

maintainable way of injecting dependencies in angularjs

I am wondering how can I inject dependencies in more readable way in angular. I am more interested in AMD(requirejs) way. Like following:
define(function (require) {
var ModuleOne = require("ModuleOne"),
ModuleTwo = require("ModuleTwo");
var ThisModule = (function () {
// code here
})();
return ThisModule;
});
Is it possible to inject dependencies above way in angularjs or is there any better way to do it then current way in angularjs?
From the Angular JS official website
Angular modules solve the problem of removing global state from the
application and provide a way of configuring the injector. As opposed
to AMD or require.js modules, Angular modules don't try to solve the
problem of script load ordering or lazy script fetching. These goals
are orthogonal and both module systems can live side by side and
fulfil their goals.
Hence, purpose of both the libraries(RequireJS and AngularJS) is totally different. The dependency injection system built into AngularJS deals with the objects needed in a component; while dependency management in RequireJS deals with the modules or, JavaScript files.
In requireJS, Objects of loaded modules are cached and they are served when same modules are requested again. On the other hand, AngularJS maintains an injector with a list of names and corresponding objects. In this case, Object is served whenever it is referenced using the registered name.
Generally we inject dependencies in angularJS like
someModule.controller('MyController', function($scope,greeter){
});
If you want an alternative way to inject dependencies in angularJS, you may do something like.
var MyController = function($scope, greeter) {
// ...
}
MyController.$inject = ['$scope', 'greeter'];
someModule.controller('MyController', MyController);
Hope it helps!

Require pattern Browserify / Angular

I'm working in a project with angular and browserify, this is the first time for me to use this two tools together, so I would like some advice on which is the way to require files with browserify.
We may import those files in different ways, Until now I experimented this way:
Angular App:
app
_follow
- followController.js
- followDirective.js
- followService.js
- require.js
- app.js
For each folder with in the files for a plugin I created an require.js file and in it I require all the files of that folder. Like so:
var mnm = require('angular').module('mnm');
mnm.factory('FollowService', ['Restangular',require('./followService')]);
mnm.controller('FollowController',['$scope','FollowService',require('./followController')])
mnm.directive('mnmFollowers', ['FollowService',require('./followDirective')]);
and then require all require.js files in a unique file called app.js that will generate the bundle.js
Question:
This way to require the files can be a good structure, or it will have some problem when I need to test? I would like to see your way to achieve good structure with angular and browserify
AngularJS and browserify aren't, sadly, a great match. Certainly not like React and browserify, but I digress.
What has worked for me is having each file as an AngularJS module (because each file is already a CommonJS module) and having the files export their AngularJS module name.
So your example would look like this:
app/
app.js
follow/
controllers.js
directives.js
services.js
index.js
The app.js would look something like this:
var angular = require('angular');
var app = angular.module('mnm', [
require('./follow')
]);
// more code here
angular.bootstrap(document.body, ['mnm']);
The follow/index.js would look something like this:
var angular = require('angular');
var app = angular.module('mnm.follow', [
require('./controllers'),
require('./directives'),
require('./services')
]);
module.exports = app.name;
The follow/controllers.js would look something like this:
var angular = require('angular');
var app = angular.module('mnm.follow.controllers', [
require('./services'), // internal dependency
'ui.router' // external dependency from earlier require or <script/>
// more dependencies ...
]);
app.controller('FollowController', ['$scope', 'FollowService', function ...]);
// more code here
module.exports = app.name;
And so on.
The advantage of this approach is that you keep your dependencies as explicit as possible (i.e. inside the CommonJS module that actually needs them) and the one-to-one mapping between CommonJS module paths and AngularJS module names prevents nasty surprises.
The most obvious problem with your approach is that you're keeping the actual dependencies that will be injected separate from the function that expects them, so if a function's dependencies change, you have to touch two files instead of one. This is a code smell (i.e. a bad thing).
For testability either approach should work as Angular's module system is essentially a giant blob and importing two modules that both define the same name will override each other.
EDIT (two years later): Some other people (both here and elsewhere) have suggested alternative approaches so I should probably address them and what the trade-offs are:
Have one global AngularJS module for your entire app and just do requires for side-effects (i.e. don't have the sub-modules export anything but manipulate the global angular object).
This seems to be the most common solution but kind of flies in the face of having modules at all. This seems to be the most pragmatic approach however and if you're using AngularJS you're already polluting globals so I guess having purely side-effect based modules is the least of your architectural problems.
Concatenate your AngularJS app code before passing it to Browserify.
This is the most literal solution to "let's combine AngularJS and Browserify". It's a valid approach if you're starting from the traditional "just blindly concatenate your app files" position of AngularJS and want to add Browserify for third-party libs, so I guess that makes it valid.
As far as your app structure goes this doesn't really improve anything by adding Browserify, though.
Like 1 but with each index.js defining its own AngularJS sub-module.
This is the boilerplate approach suggested by Brian Ogden. This suffers from all the drawbacks of 1 but creates some semblance of hierarchy within AngularJS in that at least you have more than one AngularJS module and the AngularJS module names actually correspond to your directory structure.
However the major drawback is that you now have two sets of namespaces to worry about (your actual modules and your AngularJS modules) but nothing enforcing consistency between them. Not only do you have to remember to import the right modules (which again purely rely on side-effects) but you also have to remember to add them to all the right lists and add the same boilerplate to every new file. This makes refactoring incredibly unwieldy and makes this the worst option in my opinion.
If I had to chose today, I would go with 2 because it gives up all pretense of AngularJS and Browserify being able to be unified and just leaves both to do their own thing. Plus if you already have an AngularJS build system it literally just means adding an extra step for Browserify.
If you're not inheriting an AngularJS code base and want to know which approach works best for starting a new project instead: don't start a new project in AngularJS. Either pick Angular2 which supports a real module system out of the box, or switch to React or Ember which don't suffer from this problem.
I was trying to use browserify with Angular but found it got a bit messy. I didn't like the pattern of creating a named service / controller then requiring it from another location, e.g.
angular.module('myApp').controller('charts', require('./charts'));
The controller name / definition is in one file, but the function itself is in another. Also having lots of index.js files makes it really confusing if you lots of files open in an IDE.
So I put together this gulp plugin, gulp-require-angular which allows you write Angular using standard Angular syntax, all js files which contain angular modules and dependencies of angular modules which appear in your main module dependency tree are require()'d into a generated entry file, which you then use as your browserify entry file.
You can still use require() within your code base to pull in external libraries (e.g lodash) into services / filters / directives as needed.
Here's the latest Angular seed forked and updated to use gulp-require-angular.
I've used a hybrid approach much like pluma. I created ng-modules like so:
var name = 'app.core'
angular.module(name, [])
.service('srvc', ['$rootScope', '$http', require( './path/to/srvc' ))
.service('srvc2', ['$rootScope', '$http', require( './path/to/srvc2' ))
.config...
.etc
module.exports = name
I think the difference is that I don't define individual ng-modules as dependencies to the main ng-module, in this case I wouldn't define a Service as an ng-module and then list it as a dep of the app.core ng-module. I try to keep it as flat as possible:
//srvc.js - see below
module.exports = function( $rootScope, $http )
{
var api = {};
api.getAppData = function(){ ... }
api.doSomething = function(){ ... }
return api;
}
Regarding the comment of code-smell, I disagree. While it's an extra step, it allows for some great configurability in terms of testing against mock-services. For instance I use this quite a bit for testing agains services that might not have an existing server-API ready:
angular.module(name, [])
// .service('srvc', ['$rootScope', '$http', require( './path/to/srvc' ))
.service('srvc', ['$rootScope', '$http', require( './path/to/mockSrvc' ))
So any controller or object dependent on srvc doesn't know which it is getting. I could see this getting a bit convoluted in terms of services being dependent on other services, but that to me is bad design. I prefer to use ng's event system to communicate betw. services so that you keep their coupling down.
Alan Plum's answer is just not a great answer or at least not a great demonstration of CommonJS modules and Browserify with Angular. The claim that Browserify does not mix well with Angular, compared to React is just not true.
Browserify and a CommonJS module pattern work great with Angular, allowing you to organize by features instead of types, keep vars out of global scope and share Angular Modules across apps easily. Not to mention you do not need to ever add a single <script> to your HTML ever again thanks to Browserify finding all your dependencies.
What is particular flawed in Alan Plum's answer is not letting requires in each index.js for each folder dictate dependencies for Angular modules, controllers, services, configurations, routes etc. There is no need for a single require in the Angular.module instantiation, nor a single module.exports as in the context that Alan Plum's answer suggests.
See here for a better module pattern for Angular using Browserify: https://github.com/Sweetog/yet-another-angular-boilerplate

load fabric js in angular application

So i downloaded and installed fabricjs using bower inside of my angular application and i am having trouble loading it up.
I have the following on top of my app.js file. Everything else loads fine except fabric
angular
.module('myApp', [
'flow',
'fabric',
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'ui.bootstrap',
'ui.router',
'controllers.main',
])
.config( function ($stateProvider, $httpProvider, flowFactoryProvider ) {
When i load the page i get the following error.
[$injector:modulerr] Failed to instantiate module fabric due to: [$injector:nomod] Module 'fabric' is not available! You either misspelled the module name or forgot to load it.
I am loading it up in my index.html
<script src="bower_components/fabric/dist/fabric.min.js"></script>
Anyone have any success with loading fabric inside of their angular application?
Even though this is old, I'll try to answer it for future searchers.
I've been using Fabric inside Angular with great success.
From what I can see in your code example, you are attempting to use the standard fabic.min.js file as a Angular Module. Angular only sees it as pure JS, that is why it generates an error saying it couldn't find it - because no Angular module called "fabric" was ever declared like:
angular.module('fabric', []);
If you compare one of the other modules you had listed, say ngCookies, you can see how one is setup.
It would be too much code to post here, so the easiest solution is to utilize or study some of the excellent work by Michael Calkins here:
https://github.com/michaeljcalkins/angular-fabric
He has everything wrapped up in directives and such which makes it easy to implement.
You can also play around with it live here: http://codepen.io/michaeljcalkins/pen/Imupw
Hope that helps someone.

Categories