I have a global variable declared outside of angular context:
var globalv = "Hello";
This variable does not change. I have a directive that wants to use it...
$scope.somevar = globalv + "_";
What is the simplest way to include the globalv in my angularjs app/context? When I attempt to reference it in the above manner, I get an error.
I would consider wrapping the value in an angular constant which will enable you to inject it only where its needed
var myApp = angular.module('myApplication',[]);
myApp.constant('myConstant', globalv);
Just ensure that the globalv variable is defined before your angular module is defined.
I like this better than using a rootscope/global variable since you can control who the consumers of the value are.
You can inject the constant like so:
mayApp.directive('myDirective',['myConstant',
function (myConstant) {
return {
..
};
}]);
Is there any reason why you couldn't include it in the angular context? If it absolutely needs to be global you can add it to the rootscope within the angular context.
/* declare rootscope variables when the angular app starts*/
angular.module('someApp').run(function ($rootScope) {
$rootscope.globalv = "Hello";
});
You can then reference that rootscope variable anywhere within your angular app.
This is pretty simple to me, but I personally hate using $rootScope unless I have to. You should really try and get away from global variables.
Related
I need to use this NoSleep.js inside my AngularJs controller. I installed NoSleep using bower but I need to inject it to my angularjs controller, but I have no idea on how do it, NoSleep isn't an angular service and I need to use this declaration var noSleep = new NoSleep(); in order to use it.
I'm using babel, webpack, gulp, karma
Any advise?
Typically when using non-angularjs libraries in an Angularjs application they are wrapped in a module. Then you inject the module into your app and then inject the service/factory you've wrapped with this into your controllers as needed, so you'd create a module that looks something like this:
(() => {
"use strict"
angular.module('nosleep.module', []).factory('nosleep', ['', function () {
return new NoSleep()
}])
})()
Then you'd inject the module into your main application module with something like:
angular.module('myApp', '[nosleep-module')
Then in your controllers that require access to nosleep you'd inject nosleep.
class myController {
constructor(nosleep) {
this.nosleep = nosleep
}
}
Then from within your control your can address it with this.nosleep.
It looks like NoSleep just declares a function in the global scope, so you could do something like this:
NoSleepService.js
(function () {
// place noSleep minified code here
angular.module('myApp').service('noSleep', NoSleep);
})()
That will create a NoSleep object within the enclosing function so that it doesn't pollute the global scope and register a new instance of it to your angular app.
If you have any JS lib and it's not an Angularjs lib, just add it using script tag in the html file and call it like you used to before they create AngularJs.
Have you tried it ?
Or go to the other way and wrap the lib with AgnularJs service (write an AngularJs service and call the lib method inside it), then inject this new service anywhere you want.
Update:
What #Mike Feltman and #richbai90 said in their answers was good and maybe enough for you, but I think it's better to build your service and call a methods you created, but inside these method use what ever library you want (it'll be like using interfaces in C#):
(function() {
'use strict';
angular.module('nosleep.module', []).service('nosleep', ['', nosleepFunc]);
function nosleepFunc() {
var nosleepObj = new NoSleep();
var service = {
method1: method1,
method2: method2
//... etc
};
function method1() {
return nosleepObj.method1();
}
// ..... other methods
return service;
}
})();
This way if you wanted to change nosleep lib to another one, and that new one lib has another method names, you need only to change in your service code.
I'm new in AngularJS and I'm doing a refactor of an AngularJS application and I noticed that there is a single controller file with a lot of functions that manipulate and set scope variables.
Following an example:
test.controller('testCtrl', function testCtrl($scope) {
$scope.init_filters = function() {
$scope.filter_1 = [];
$scope.filter_2 = [];
$scope.filter_3 = [];
$scope.filter_4 = [];
$scope.filter_5 = [];
};
$scope.showChanges = function() {
if ($scope.item_list.length > 0) {
$scope.messages = [];
for (var i = 0; i < $scope.item_list.length; i++) {
$scope.messages.push($scope.item_list[i].message);
}
$scope.another_function();
}else{
// other stuff
}
};
//other functions like these
}
So, I would like to split these functions in multiple JS files. I searched about this problem and I found that in a lot of case is used a service. But I think that this is not my case, because I need to working on directly on the controller's scope.
I mean, I don't want a separated function that get as parameters some scope variables and return the variable.
So, what is the best practices for doing something like this? is it possible?
If you want to use multiple files then split the definition to multiple files by passing the scope to another method and then define the rest of methods there.
File1
app.controller('CtrlOne', function($scope){
app.expandControllerCtrlOne($scope);
});
File2
app.expandControllerCtrlOne = function($scope)
{
}
Check this video
As you said the code you found for controller is large one so there are multiple ways in angular js that you can implemented the separation of code.
I will suggest you to go with following approach:
Use service to add those code in it which you need in other places as well and you know that this code does not require scope object..
Use factory to add some Utility kind of functions. The collection of logic which does not require scope object again...
As controller code is too large, I think View/UI of same also being as per wrote...
So for this you can go with creating directives for section in view..
Where-ever you think this peace of view section can be separate and standalone logical functionality that you can move into directive.
There are three ways to create directive with scopes:
A. Shared Scope B. Isolated Scope C: shared and Isolated scope
In this ways may you can at-least make your controller code readable and looks modular.
Let say::
module.controller('longRunController', function() {
#TYPE 1 code
// some code which fetch dat from API
// some code which save variable and objects which can used in another controller or directives
// some code which need to passed to other controller even after route changes
#TYPE 2
// some code which is only related this controller but has some bussiness logic
// some code which is a kind of utility functino
#TYPE 3
// all $scope related variable $watch, $scope and related variables
// some code of perticular section of which VIEW which handle by this controller
});
Consider in above patter your controller code has:
So type 1 code can be moved to Service
type 2 code can be moved to factory
type 3 code can be move to directives
you can pass $scope as a parameter to the external function.
And because you just use the objectreference, all changes you made in your external functions are made on the $scope object from your controller.
test.controller('testCtrl', function testCtrl($scope)
{
showChanges($scope);
});
...
function showChanges(scope)
{
scope.param1 = "Hello World";
}
Suppose that I have a global constant that need to be accessible in every angular module, what is the advisable approach to declare the constant. I have three approach in my mind but i not sure which to be used.
Appreciate if anyone could point out what is the benefit using Approach 2 compare to Approach 1 in this condition.
Approach 1 (pure js constant):
var jsConstant = {
constant1: 'constant1',
constant2: 'constant2'
};
angular.module('mainApp').controller(['$scope', function($scope) {
$scope.constant1 = jsConstant.constant1;
$scope.constant2 = jsConstant.constant2;
}]);
Approach 2 (pure angular constant)
angular.module('mainApp').constant('angularConstant', {
'constant1': 'constant1',
'constant2': 'constant2'
});
angular.module('mainApp').controller(['myConstant', '$scope', function(myConstant, $scope) {
$scope.constant1 = angularConstant.constant1;
$scope.constant2 = angularConstant.constant2;
}]);
Approach 3 (mixture of js and angular constant)
var jsConstant = {
constant1: 'constant1',
constant2: 'constant2'
};
angular.module('mainApp').constant('angularConstant", {
'constant1': jsConstant.constant1;
'constant2': jsConstant.constant2;
});
angular.module('mainApp').controller(['myConstant', '$scope', function(myConstant, $scope) {
$scope.constant1 = angularConstant.constant1;
$scope.constant2 = angularConstant.constant2;
}]);
Advisable way is to use constant:
(function(angular, undefined) {
'use strict';
angular.module('myApp.constants', [])
.constant('appConfig', {userRoles:['guest','user','admin']});
})(angular);
Even better way is to inject those values on every build from the server, since most of the time you want to define those values on your server and forget about managing them in other places. For that purpose take a look at ng-constant module for grunt or gulp
Edit
Approach 3 is just a messy version of Approach 2 with unnecessary declaration of JS variables outside of Angular modules
Approach 1 is not good, because you those constants are not really reusable. If you have another controller that wants to reuse those values?
In approach 1 you created a global variable jsConstants which, I believe, is not treated as a good practice - you should avoid creating global constants if possible. Moreover - properties of jsConstants are not really constant - anyone, anywhere can change them. Also, using global constant makes controllers less testable (unit), as they will depend on this global object.
In approach 2 I believe you are not allowed to change these values, so they more act as constant values. You inject them in controllers, so they are still unit-testable.
I am newbie to Angular.js , i have read that Controllers should not pollute the global namespace.
What does it really means
and why angular.module('SomeApp',[]).controller('SomeController', function($scope) {})
is the best way to add a controller?
Edit: Polluting the global namespace is not specific to Angular, but to Javascript (and actually any dynamic-typed language, where variables could appear or be redeclared in almost any scope).
Polluting the global namespace would make unavailable -actually: will override- certain names among modules.
Imagine I have a module A in 'a.js' where I declare:
mymodule = angular.module('A');
function Foo($s, $http){ ... };
foo = mymodule.controller('foo', ['$scope', Foo]);
Also imagine I included, beforehand, a script named 'utils.js':
foo = 3;
foo in a.js would override foo in my utils script. That is polluting the global namespace and that's why it's a bad idea (perhaps I actually NEEDED the foo var).
Want to have code like that instead of chaining the calls? use a closure:
/* a.js */
(function(){
var mymodule = angular.module('A');
function Foo($s, $http){ ... };
var foo = mymodule.controller('foo', ['$scope', Foo]);
})();
And so, you will not pollute the global namespace since each declaration is inside the anonymous function call.
That format you used
angular.module('SomeApp',[]).controller('SomeController', function($scope) {})
does not pollute the global namespace.
This format would however:
Javascript
function UserController($scope) { ... }
HTML
<div ng-controller="UserController">
That is because the controller function is globally available outside of the scope of the angular application
I am trying to re-write an application using angular.js, but I still do not see how it works (more or less).
For instance. In my previous code, I had a function that was executed once everything was loaded that initialised variables, accessed for everyone in a window.variable style.
Now I want the same here.
My idea was to build a factory to return an object with all the variables, and then make that everyone had access to this object (somehow).
The questions are:
1- Am I right? I should initialise variables through a factory?
2- And how can I "call" this factory-method at the beginning of the code? with the module.run function?
Cheers,
I'd probably put the variables in a service, and then inject that into a wrapping angular controller. Any other controllers that you would want to have access to these 'global' variables would be nested under the wrapping controller, thus inheriting the variables.
var app = angular.module("app", []);
app.service("globVars", function () {
var vars = {};
vars.someVar = "a";
vars.someOtherVar = "b";
return vars;
});
app.controller("WrappingCtrl", function ($scope, globVars) {
$scope.globVars = globVars;
});
app.controller("NestedCtrl", function ($scope) {
console.log($scope.globVars.someVar); // => "a"
});
<html ng-app="app">
<div id="wrapper" ng-controller="WrappingCtrl">
<div class="nested" ng-controller="NestedCtrl">
{{globVars.someVar}}
</div>
</div>
</html>
I think you should avoid using global variables as much as you could
But if you have to use them, you are right, you can initialize them in module.run and add the module in the app dependencies
If you want to access some variables, you must see to $rootScope, because you can access $rootScope everywhere.
Also you must use angular config and run functions.
I advice to you don't use global scope, because it affects on app speed, memory leaks etc.