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.
Related
If the right way to share data between controllers are using factory/service, what is the purpose of the $rootScope?
$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
As per my understanding.
you can use $rootScope in multiple places .
global settings defined in factory and then in view you can update as per your condition. f.x layout manipulation
you can assigned $state on run.
you can handle error ($rootScope.$on(...)
I hope this will help.
Thanks
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.
Here's something simple and I think there must be a better way: I often need to navigate to a new view, and at the same time I want to provide some context information to the scope that will be created. I can't figure out how to do both simply -- change the url (resulting in my view/controller being instantiated) and pass some variables I want instantiated in the controller's scope -- for instance, so they can be rendered in the view template
So instead I am doing:
$rootScope.myVar = 'blah';
$location.path = '/newView' ;
and newView.html accesses {{myVar}}
I know this is wrong, what is the simplest solution to avoid using $rootScope like a global dumping ground?
I have a controller where the $scope object has been used to store methods and values that are only used locally within the same controller. There is a lot of this going on:
$scope.foo = 'something';
$scope.bar = 'something else';
... and so on. None of these values are used within the view. My question is does polluting the $scope object affect performance? Is it a good idea to clean this up so only values and methods needed for the view are contained in the $scope object?
Yes, Polluting $scope does affect performance, but its depends your scope has multiple watchers which are frequently changing then that will create a more overhead cost. Refer this answer which has covered same point
For avoiding this situation I'd suggest you to do good re-factoring of code
Handle all the logic in controller whenever required otherwise do separate a logic by making good use of each component.
Move common method(logic) to service/factory/provider which is used in multiple place, so that it would be sharable.
If some value are fixed, they are not gonna change then move them to constant/value
Whenever you feel like you have same logic which needs to be keep in $scope it self then move that logic to common controller. When required you could inject in your current controller scope using $controller injector
Also refer Understanding Of Scope for clear understanding of use of scope
I am looking at some samples of how controllers work in angular and I see two ways of declaring them, one with just controller name and one with "as somename". Examples that use ng-controller = "myController" take a $scope as dependency when defining controller.
Then model is then set on the $scope, something like this
$scope.mymodel = somevalue;
Example that uses "as" syntax such as ng-controller = "MyControler as vm" never uses $scope when setting up the model but ratther assigns it to "this" and binds using {{vm.something}}.
in controller:
var vm =this;
vm.something = somevalue;
How is that working in second example? Is that new way in latest version?
Using the "as" syntax exposes your entire controller to your view. In my opinion, that is a bad practice. Although I'm not sure which one is better performance wise, but using 'this' in javascript already has plenty of issues of its own, and I don't recommend adding another meaning to 'this'. So I would stick to $scope (since that is what they're using in the docs as well).
See this topic if you want to know more context about how the 'as' syntax work: 'this' vs $scope in AngularJS controllers