I have a variable that I declared in rootscope to share among other controllers.
I also need to place more than one variable in the rootscope.
Syntactically, how would you do that.
This is my definition for declaring just one variable in rootscope.
(function (module)
{
angular.module("sample", []).run(["$rootScope", function($rootScope){$rootScope.TaxPercent = 30;}]);
.
.
.
}
$rootScope is an object, so just assign properties:
$rootScope.TaxPercent1 = 30;
$rootScope.TaxPercent2 = 40;
Or
$rootScope.TaxPercent = {percent1: 30, percent2: 40}; // SET
console.log($rootScope.TaxPercent.percent1); // GET
But NOT:
$rootScope = {percent1: 30, percent2: 40};
Because you'll overwrite all the previously data set to the object
In general $rootScope shouldn't be used to share variables for different and many reasons that have been explained before in articles like:
here
What will happen if you forget about your $rootScope.TaxPercent = 30; global variable and then you create a variable $scope.TaxPercent inside your controller? That would cause problems for sure.
Just providing an option here and suggesting the use of Angular Services
Here is a sample example of how Angular Service work
From the Angular FAQ page:
Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. If you're tempted to put a function on $rootScope, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.
Related
Is it advisable to store data in $rootScope.
I have a cordova app which uses sensor data which is coming every 100ms. For me to use that data in multiple controller I am using $rootScope.sensorData variable which is being refreshed every 100ms. Is it alright to use it this way? Is there a better way to do it?
Thank you
You can store it in factory. In AngularJS factory is singleton, so only instance is created.
myApp.factory('SensorSrv', function SensorSrv() {
var sensorData;
return {
setData: setData,
getData: getData
};
function setData(data) {
sensorData = data;
}
function getData() {
return sensorData;
}
});
You can also user local-storage if you want to persist the data.
I think this is not good idea to use $rootScope in entire code logic , There are lot of reasons behind that ... Instead of that you can create code login in services it is more flexible ... and also you can see this link
Best practice for using $rootscope in an Angularjs application?
From the Official Docs:
$rootScope exists, but it can be used for evil
Scopes in Angular form a hierarchy, prototypally inheriting from a root scope at the top of the tree. Usually this can be ignored, since most views have a controller, and therefore a scope, of their own.
Occasionally there are pieces of data that you want to make global to the whole app. For these, you can inject $rootScope and set values on it like any other scope. Since the scopes inherit from the root scope, these values will be available to the expressions attached to directives like ng-show just like values on your local $scope.
Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. If you're tempted to put a function on $rootScope, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.
Conversely, don't create a service whose only purpose in life is to store and return bits of data.
--AngularJS Miscellaneous FAQ
I recommend using app.value app.value('test', 20);
Because by using $rootScope you are exposing that value to all the services which might be a security threat. By using value you can make sure where do you want to use that variable according to your requirement.
I would like to persuade my co-worker that it is a better approach to use component directives than to use $rootScope everywhere. I need arguments against his ones because he is very stubborn and a very good speaker (which I am not). He thinks that $rootScope prevents spaghetti code. This week I have refactored the project and there are no more spaghetti but I don't want him to rework everything to $rootScope.
Please tell me about problems and issues that can arise when using $rootScope. Thank you.
EDIT
Are there any security issues with $rootScope?
EDIT 2
My friend came with this construct and wants to put it in every component:
function Controller(service, $rootScope, $scope) {
var vm = this;
$scope.a = $rootScope.a;
$scope.b = $rootScope.b;
$scope.c = $rootScope.c;
$rootScope.$watch('mapLoaded', function () {
$scope.a = $rootScope.a;
$scope.b = $rootScope.b;
$scope.c = $rootScope.c;
}, true);
Would the issue of destroying scopes and removing wathces that #charlietfl described in comments appear? I am definitelly not gonna let him code like this but I need the arguments against it. Thanks again.
$rootScope exists, but it can be used for evil
Scopes in Angular form a hierarchy, prototypally inheriting from a root scope at the top of the tree. Usually this can be ignored, since most views have a controller, and therefore a scope, of their own.
Occasionally there are pieces of data that you want to make global to the whole app. For these, you can inject $rootScope and set values on it like any other scope. Since the scopes inherit from the root scope, these values will be available to the expressions attached to directives like ng-show just like values on your local $scope.
Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. If you're tempted to put a function on $rootScope, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.
Conversely, don't create a service whose only purpose in life is to store and return bits of data.
-- AngularJS FAQ
I will response myself to Edit 2 citing this:
Using $watch means whenever you read this code in the future you’ll
have to consider whether it’s being triggered by something else, too.
I've been using var and $scope.varname and both work fine in AngularJS. I was wondering if there was a difference between the two functionally, and what best practice was in which one to use?
Yes! $scope variables bind to the view where as var does not and is local to the function it was declared in!
var x = 3;
$scope.y = 3;
{{x}} - undefined
{{y}} - 3
The technical implications of using var and $scope have been described by #tymeJV and others. I think the next logical question answer is: When do I use either?
TL;DR - if you do not use a variable in a view (e.g. {{myVar}} ), use var.
The reason is two fold:
Encapsulation - hide state that is not necessary to the view. This will prevent unintended modifications of the variable.
Performance (prevent extra digest cycles) - Angular performs "dirty state" checking on variables. Modifying a variable that's not used in the view may cause extra digest cycles unnecessarily. In an application with a couple of ng-repeats and a bunch of watches, this can have a huge impact.
1 - $scope, is the glue between your controller and your view/model , when you are defining a variable/function to the $scope of a controller, your whole view , which this controller controls it ! , can see that variable/function . Where a pure variable just works in that controller , not even the view of that controller!
2- Every thing that has been defined to the $scope , is manupulatable from the outside of the controller , throughout the Directives , Services , your html view ... , while a pure variable is NOT;
Simply spoken - all variables you define on $scope, e.g. in your controller, are available in your html markup. in case you need a variable just inside your js functions, you can declare it with var, they are only locally available. Same with functions.
$scope bind value to the view and var is the local variable to the application.
I just now learned that Angular has global variables:
Angular Values
var app = angular.module('mySuperDuperApp', ['SomeExternalModule']);
// Define global variables
app.value('globals', {
db : null,
databasename : "serviceapp",
image_max_height: 620,
image_quality: 0.7
}
);
Some questions regarding usage.
Can a global variable have its value changed?
To change it (if possible) can I just refer to it by it's name such as db in any controller script?
Can I access a global variable in my HTML with just the name only?
A variable loaded into a value provider isn't really a global in the traditional sense. It doesn't sit in the global name space. The provider needs to be injected anywhere you use it so it's a bit more akin to an object in an OO sense.
A value provider is a way to allow many different components access to a variable, so I see why you're calling it a global. But a value is a good way to share data without many of the risks of actual globals.
You might check out the different kinds of providers here Provider docs of which you'll see value is just one.
1) You can change an Angular value (but not a const which is closely related)
2) You need to inject the value wherever you use it and then prefix it with the name of your value For example:
app.controller('Ctrl', function($scope, global ) {
console.log(global.db);
global.databasename = "newname";
});
3) You can access the value from HTML if you copy the value on to the appropriate scope:
app.controller('Ctrl', function($scope, global ) {
$scope.db = global.db;
});
You can inject those values just like you would inject a controller or a service and can modify them just like you would any other injected object.
app.controller("mySuperDuperController", function ($scope, 'globals') {
$scope.globals = globals; // <-- to access them in the template
globals.db = 'newDb'; // <-- modify their value.
});
Is it correct to pass the "current" $scope to an AngularJS service?
I'm in the situation where I've a $service knowing it's consumed by only one controller, and I'd like to have a reference to the controller's scope in the $service methods themselves.
Is this philosophically correct?
Or I'd better to broadcast events to the $rootScope and then make my controller listen to them?
To let the controller know when something async happens, use Angular promises.
To provoke the $apply, you don't need the scope, you can call $rootScope.$apply, as there is no difference calling it in a specific scope or in the root.
Regarding the variable reading, it would be better if you received parameters. But you could also read it from a scope as an object parameter, but I would go with parameter, that would make your service interface much more clearer.
I would say if your functionality is specific to one controller only than you don't need a service.
The controllers tasks is to manipulate the specific model whereas a service should deal with global tasks. I would rather stick to this paradigm instead of mixing things up.
This is what the docs say
Service
Angular services are singletons that carry out specific tasks common to web apps
Controller
In Angular, a controller is a JavaScript function(type/class) that is used to augment instances of angular Scope, excluding the root scope.
PS: Apart from that if you need to digest you can also inject the $rootScope within your service.
Yes. You can pass the $scope into the service when you initialize it. In the service constructor you can assign the scope to something like this._scope and then reference the scope within the service!
angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {
$scope.someVar = 4;
$scope.blahService = new blahService($scope);
});
angular.module('blah').factory('blahService', function() {
//constructor
function blahService(scope) {
this._scope = scope;
this._someFunction()
}
//wherever you'd reference the scope
blahService.prototype._someFunction = function() {
this._scope['someVar'] = 5;
}
return blahService;
});
I personally believe that passing the whole $scope to a service is a bad idea, because it creates a kinda circular reference: the controller depends on the service and the service depends on the scope of the controller.
On top of being confusing in terms of relations, things like this one end up getting in the way of the garbage collector.
My preferred approach is to put a domain object in the controller scope and pass that to the service. This way the service works regardless whether it's used inside a controller or maybe inside another service in the future.
For example, if the service is supposed to push and pop elements from an array errors, my code will be:
var errors = [];
$scope.errors = errors;
$scope.myService = new MyService(errors);
The service interacts then with the controller by operating on errors.
Of course I've got to be cautious about never wiping out the whole array reference, but at the end of the day that's a general JS concern.
I'd never want to use broadcasting, $apply and/or similar things, because imho good OO-practices will always trump whatever Angular-magics.