I am developing an Angular JS application.
I would like to know what is the best practice to include string values in our code.
I am planning to use another JS File which contains all the constant values. I will call this JS file in each and every JS(Controller) to refer the string values.
You can define constants in angular like
angular.module('moduleName',[]).constant('constName',string|object|array);
You can inject in directive or controller or wherever you want.
angular.module('moduleName',[]).directive('directiveName', ['constName', function(constName){...});
You have several options.
Global value. You can use your constants in form of the javascript object which would be globally accessible across the application. For example, your file could look something like this:
config = {
host: 'domain',
port: '1234'
};
Obvious disadvantage is that those values are not really a constants and can be easily changed, so it's error prone.
Angular config module. More reliable and cleaner option is to create a separate module to be used as a dependency for main app module. You would still have separate file for your constants but instead of some global variable this file would hold angular module with constant service. Something like this:
angular.module('app.config', []).constant('config', {
host: 'domain',
port: '1234'
});
Then in main application you would configure app like
angular.module('app', ['app.config']).config(function(config) {
// console.log(config);
});
Here is the sample code;
var app = angular.module('plunker', []);
app.constant('configs', {host:'localhost',port:8080});
app.controller('MainCtrl', function($scope, configs) {
$scope.name = configs.host;
});
here is demo plunker
Angular has a built in way of providing constants, e.g:
angular.module('foo', ['ngRoute']) // Your angularjs module
// Decide a name for the bucket of constants, then just declare the
// constants in turn as an object literal:
.constant("HTTP_CONSTANTS", {
"URL": "http://localhost",
"PORT": "80"
})
Then you can load it anywhere where you have access too you foo module using dependency injection, i.e.:
angular.module('foo')
.controller('bar', function (HTTP_CONSTANTS) {
... // Use HTTP_CONSTANTS.URL or HTTP_CONSTANTS.PORT, for example
})
Here's a good primer on using constants:
http://twofuckingdevelopers.com/2014/06/angularjs-best-practices-001-constants/
You can use factory for this purpose and inject this factory where ever you want these constants.
var app=angular.module('Myapp', []);
app.factory('ConstantService', function(){
var constant={temp:'c'};
var getConstants=function(){
return constant;
};
return{
constants:getConstants;
}
});
app.controller('MyController',['ConstantService' function (ConstantService){
var constant= ConstantService.constants;
}]);
Related
I have a constant value that is common throughout my project, among 2 of my modules- I want to have a design that I would have to only define it in one module and pass on the value to another module. How can I ?-
Module1 is like
var myApp = angular.module('myApp', ['ui.router']);
myApp.constant('constVar', 'http://45.26365.23/mydata/');
and Module2 is like
var Dashboardapp =angular.module('Dashboardapp', ['ui.router']);
Dashboardapp.constant('constVar', 'http://45.26365.23/mydata/');
For the record, the Google internal style guide says "do not define variables on the scope." (It actually explicitly says that). Note that means in particular, but not only, $rootScope (your code would be guaranteed to get kicked back in review if you did that, with very ugly "THIS IS BAD" comments).
Just define it at a higher level then both modules, typically at the app level (Angular 1.x defines a configurable place for constants in the app config API, you may want to look that up, this is useful because it actually enforces the constant). You can also just use a class defined in no module at all (just a top level class that you import and use statically), or you can define another module that you inject (which might be overkill for a few simple constants).
A naive approach would be to define the constant outside the modules:
var myConstant = 'http://45.26365.23/mydata/';
or maybe even better if you have more constants or other general data:
var myConfig = {
myConstant : 'http://45.26365.23/mydata/'
// other data
}
and then call it in the modules:
var myApp = angular.module('myApp', ['ui.router']);
myApp.constant('constVar', myConfig.myConstant);
var Dashboardapp =angular.module('Dashboardapp', ['ui.router']);
Dashboardapp.constant('constVar', myConfig.myConstant);
Other possibility would be to define it in only one module, which would be your main module, and inject it in the other modules:
var myApp = angular.module('myApp', ['ui.router']);
myApp.constant('constVar', 'http://45.26365.23/mydata/');
var Dashboardapp =angular.module('Dashboardapp', ['ui.router', 'myApp']);
Dashboardapp.constant('constVar', myApp.constant);
Instead of the last line you could just call the constant where ever it is needed.
You could always use the 'constant' that Angular comes with ...
import * as angular from 'angular';
export default angular
.module('app.constants.foo', [])
.constant('fooAction', Object.freeze({
name: value
}))
.name;
Then you inject your named constant. Thus it is accessible anywhere in the app (and more importantly immutable (mostly)).
Suppose that I have an SPA written via AngularJS 1.x.
It has a single app module defined like this:
var app = angular.module('app', ['ngAlertify', 'ngRoute', 'ui.bootstrap'])
I also have several controllers which are defined in separate *Ctrl.js-files. What is the appropriate way to define them?
I see two options here. The first one is
app.controller('LoginCtrl', function($scope) { /* ... */ });
and the second one is
angular.module('app').controller('LoginCtrl', function($scope) { /* ... */ });
Which one is better and most common-used practice? Is there any downsides of using either of them?
If I understand your question correctly then you wan to know different between
app.controller('LoginCtrl', function($scope) { /* ... */ });
vs
angular.module('app').controller('LoginCtrl', function($scope) { /* ... */ });
In above two in first method app is a global object which you declared somewhere i.e. in app.js like
var app = angular.module('app',[]);
In this case app is a global variable which will be accessible throughout your entire application. which I believe is not a good thing to use global variable
in our application.
In second method we are using global angular object to create a controller so that in this we will not be using global variable. In this case app.js will look like
(function(){
'use strict';
var app = angular.module('app', []);
....
....
....
....
})
In this case app variable will not be available anywhere apart from this file.
So I belive second method is better than first one.
My personal preference is to use app.controller('LoginCtrl', function($scope) { /* ... */ }); as this makes it easier to reuse the controller in another project with little to no changes, without those annoying module not found errors because you forgot to rename the module when reusing the file
I think that depends a bit on the personal style of writing. One thing is that while working with AngularJS 1.x.x you can have different styles of writing code, method stacking etc.
Personally, I prefer app.controller('LoginCtrl', function($scope) { /* ... */ }); mainly because you can easily preview your controller and distinguish it from thge module. Another bonus I see of having a clearly defined separate module is that you can easily check what includes you have ('ngAlertify', 'ngRoute', 'ui.bootstrap').
Most commonly used as far I have seen, even here on SO, is the method that I previously mentioned. Yet again this is something that is more reflective of personal style rather than strong pre-requirements of writing code. I hope that helps to some extend.
None of the above. The purpose of modules is to keep the application modular and not pollute global scope.
You can have var app = ... but this should be done inside IIFE once per file.
Another issue with modules is the precedence. If the application uses angular.module('app') module getter, the files should be loaded in specific order, in order for the module to be defined when it is retrieved in other files. This creates problems if they aren't, for example when they are concatenated in alphabetic order.
The solution is to use one module per file. This makes the application truly modular, independent of file loading order, also benefits testability. See also this answer for how this pattern supposed to work.
You can use module setter and getter methods for implementation of controllers in different file.
Suppose myApp.module.js
angular.module('myApp', []); //Setter method, registring module
In myApp.homeCtrl.js
var myApp = angular.module('myApp'); // getter method, getting the module already registered.
myApp.controller('homeCtrl', [function()]{ })
For more info check this https://toddmotto.com/angular-modules-setters-getters/
The second approach your are taking about is better because it uses the already created module and doesn't create the new module but with the first approach you are using global variable that is not recommended
I would like to know what is the best way to reuse the same directive for multiple modules. In my mind i think directives are like DOM-modules, so the architecture of angular for this is a bit annoying of my point of view.
The way I'm doing it now is:
var mainapp = angular.module('MainApp');
mainapp.controller( ... );
var otherapp = angular.module('OtherApp');
otherapp.controller( ... );
And in other file i have my directive i want to use in this two controllers/modules
mainapp.directive('autoselect', function(){ ... });
But as you can see, I have to specify in what app I have to use it. If I want to use in both, do i have to copy twice the same code?
You can maintain a module that contains common (services, directives, values, constants etc.) and inject into each module.
angular.module('CommonApp',['OtherCommonModule1','OtherCommonModule2']).directive(..);
var mainapp = angular.module('MainApp', ['CommonApp']);
mainapp.controller( ... );
var otherapp = angular.module('OtherApp', ['CommonApp']);
otherapp.controller( ... );
No, you don't have to specify which app/module you need to use a directive in.
Let me explain:
In angularJS, everything is a module. For example, MainApp, OtherApp and even the autoselect directive is a module.
Each module can 'depend' on one or more modules.
So, here's how I would design the solution:
angular.module('com.example.mydirective', [])
.directive('autoselect', function() { ... });
angular.module('MainApp', ['com.example.mydirective']);
.controller(...);
angular.module('OtherApp', ['com.example.mydirective']);
.controller(...);
One thing I'd like to add: the square brackets that denote the dependency have a special significance.
angular.module('module-name', []); // this line tells angularJS to create a new module
angular.module('module-name'); // no brackets -- this asks angularjs to return a pre-existing module
Hope this helps
I have the following lines:
var app = angular.module('app', []);
app.constant("const", {
foo: "bar",
test: "123"
});
I would like to now access the information in constant directly from the module app. Something like this didn't work:
console.log(app.constant.const.foo);
I know you can inject constants into controllers, services etc and access the information but for my purposes, I would like to access them straight off the module.
Is the only way to access a registered constant is to inject it into a controller/service/etc?
Assuming, somehow, you want an access to the const outside the angularjs environment.
Then you have to retrieve it from an injector, and there are two ways you can get the injector:
Get the current injector of a running angularjs application like this:
var injector = angular.element(document).injector(); // assuming `ng-app` is on the document
injector.get('const');
Create a new injector from existing modules:
var injector = angular.injector(['ng', 'app']); // note the 'ng' module is required this way
injector.get('const');
Example Plunker: http://plnkr.co/edit/ld7LLlr94N7PiqnxY5zH
Hope this helps.
If you really want to access the constant directly, you could do:
var app = angular.module('app', []);
var app.constants = {foo: "bar", test: "123"};
app.constant("const", app.constants);
console.log(app.constants.foo);
But, I don't see a real benefit ;)
I want to follow angularjs recommendation (http://docs.angularjs.org/guide/module):
While the example above is simple, it will not scale to large
applications. Instead we recommend that you break your application to
multiple modules like this:
A service module, for service declaration A directive module, for
directive declaration A filter module, for filter declaration And an
application level module which depends on the above modules, and which
has initialization code.
So I've created services.js file that only contains:
window.myservices = angular.module('services', []);
And then I added a few services where each service file starts with:
window.myservices.factory('service1', function() {
....
});
I made the same for filters.js and directives.js.
In my app.js file I made:
window.App = angular.module('app', ['services', 'filters', 'directives']).
// run \ config \ whatever
How can I do it without making variables on window?
There's no need for globals at all:
// Define your services
angular.module('services', [])
.factory('service1', function(){})
.factory('service2', function(){});
// Define you main app module and specify the dependencies
angular.module('MyApp', ['services']);
As Stewie said, you can use angular.modue('service',[]);
However you only need to do this in the first loaded file, like so:
file1.js
var mod = angular.module('service',['dependancy']);
file2.js
var mod = angular.module('service');
index.html
<script src="/scripts/file1.js"></script>
<script src="/scripts/file2.js"></script>
Another option is to use namespaces...
file1.js
var mod = angular.module('service.part1',[]);
file2.js
var mod = angular.module('service.part2',[]);
main.js
var mod = angular.moduel('service', ['service.part1','service.part2']);
EDIT (plunker):
http://plnkr.co/edit/i75A5CQeSptQjaxvR8qi?p=preview