Globally available variables with Angular - javascript

We are in the process of migrating our webapp to Angular.js. Traditionally, we created a global object named app and used it to store functions, variables, etc. that were used globally. For example, the active user's name and avatar might be stored in app.user.
With the transition to angular, app is no longer just an object, it is an angular app module. What is the correct way to store data globally like this in an Angular mindset? It could be completely different, that's fine. I just want to make sure we do it correctly.
I would do something as simple as app.global = {}; and use app.global around the site, but if the angular API ever changes to use a property named global, it would be a nightmare to fix.

Angular is fairly allergic to global variables. I would recommend using a service (e.g. UserDataService) to hold this data and injecting it where it is needed (like in a controller).
Your service will be a singleton that can be accessed wherever it is injected.

The correct way to do this would be to provide the value or function to angular's dependency injector via Module.value or Module.constant. See: http://docs.angularjs.org/api/angular.Module

Well, you can also set it in rootScope as:
var app = angular.module('appName'){
//other codes removed
});
app.run(function ($rootScope) {
    $rootScope.globalVariable = 'hello'; //global variable
});
Now you can access the globalVariable

Related

Difference between storing in app.locals vs global object

I saw some people use app.locals to store properties that is available across all views.
Also other people used global.AnyNameVariable to store anything even like requiring config.js files and etc
ex:
app.locals.objOne = {
name:'John'
}
global.objTwo = {
name:'Doe'
}
What is the difference between them? and what is the purpose? what is the right way to use both?
As the documentation states,
The app.locals object has properties that are local variables within the application.
This is application-level container provided by the framework that serves to store application settings, etc. There can be more than one Express application, while global is global.
app.locals is available as req.app.locals within middlewares, this way it can be decoupled from specific app variable.

Why would you ever use the $rootScope?

Ok so I was reading here
basically when I have this
MyApp = MyApp || {};
MyApp.settings = {
isFooEnabled: false
}
if I use the rootscope and want to check if isFooEnabled I have to inject the rootScope into whatever object I want to do the check.
How does that make sense?
What is the advantage of using $rootScope.isFooEnabled over using straight standard javascript MyApp.isFooEnabled?
what is better for what?
when should I use one over the other?
The $rootScope is the top-most scope. An app can have only one $rootScope which will be shared among all the components of an app. Hence it acts like a global variable. All other $scopes are children of the $rootScope.
The rootScope's variable is set when the module initializes, and then each of the inherited scope's get their own copy which can be set independently.
NOTE:
When you use ng-model with $rootScope objects then AngularJS updates those objects under a specific $scope of a controller but not
at global level $rootScope.
The $rootScope shouldn't be used to share variables when we have things like services and factories.
Finally, Angular FAQ says this at the bottom of the page: "Conversely, don't create a service whose only purpose in life is to store and return bits of data." See from here.
Actually, I would argue that you shouldn't use $rootScope in this case, you should create a separate service (or factory) that stores your settings, however, the usage and reasons are the same.
For simply storing values, the primary reason is consistency. Modules and dependency injection are a big part of angular to ensure you write testable code, and these all use dependency injection so that unit tests can be written easily (dependencies can be mocked). Whilst there are not many obvious gains from injecting a simple object, it's consistent with the way more complex code is accessed, and there is a lot to be said for that. On a similar note, if you were to upgrade your settings object to fetch data from the server (e.g. for environment specific settings), you might want to start unit testing that functionality, which you can't really do properly without modularising it.
There is also the (frankly weak) namespacing argument - what if another library you import uses window.MyApp?
TL;DR: It's a strongly recommended best-practice. It might seem a bit clunky now, but you'll benefit from doing it in the long run.

What is the correct way to wrap Angularjs code in a closure?

I have a simple application outlined in this question: Angular scope not affecting ng-show as expected
Which exposes my application via global variables, this is obviously not ideal.
I have tried wrapping the Angularjs code in a closure but I get errors in the browser telling me that the objects I am trying to access aren't accessable.
(function() {
// App code here
});
Is there a way to expose my app so with the current layout it functions correctly or do I need to change the whole struction of my app to achieve this.
I am ideally trying to reduce global variable pollution while keeping the app structure the same in both the html and js.
You are missing the call part.
Here is one format, there are a few others.
(function (a, b){
//Do stuff with `a` and `b`
})("a", "b");
Note the final pair of parens. Any parameter that you define, and later pass in are global within the scope.

Angular controllers: logic as methods or add to scope?

Let's say that I had a previous function that wasn't exposed via my API ,and now I decided to expose the function (in my case for test coverage).
What are the arguments for putting objects I want accessible outside of the controller constructor as a property of $scope vs. a this.propertyName on the controller?
The only logical different is that many things have access to $scope, but not everything has access to the context of the controller. A controller is just a standard Javascript constructor function, so anything that might call it as one can access things defined on this. But HTML templates cannot: they can only see things defined on $scope. So the standard is (roughly):
Controller: Use $scope for things shared by HTML templates, directives, etc. Use this for components accessed locally or in only very limited cases such as by testing harnesses (if at all).
Directive: Use $scope for anything shared by HTML templates or other directives/controllers. Avoid using this.
Service: Use this for everything you want to expose externally. Define local (private) vars for everything else.
Filter: Avoid exposing properties/methods externally. Filters aren't meant to be used that way.

Service functions outside Angularjs scope

I have created a service in angularJS that uses btford.socket-io module to interact with the server.
Since in the service I have implemented some API that I use inside angular at the moment, but for later extension of the application I also need to give access to these API outside angular scope.
So that in future one could just call the function without having the need to create controller and other stuff.
At the moment I did this for a controller
var myController = angular.element($('body')).scope().myController;
by saving the whole controller inside a scope variable.
I was wondering if it would be possible to do the same with a service.
How about:
angular.element(document.body).injector().get('MyService');
Typically not good practice. But sometimes its needed.
Note: document.body is the element Your angular application is mounted to
Another thing you might consider is 'closing' external api with angular via a factory.
eg. return your global or namespaced class or api from an angular factory.
This is essentially what angular does for you. But instead of creating the reference inside angular first and having to extract it, you'd create it outside, and register it with DI as a factory or value.

Categories

Resources