Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is storing variables in $rootScope good practice?

Update 2: I found a solution

I've altered the settings file to just a JS file, added var tempSettings = to the beginning of the file, and added it in index.html. This way it gets loaded with the initial HTML, ensuring it will exist when app.run goes. The settings service then takes this tempSettings variable and puts it in the service. To clean up, I remove the tempSettings pointer.

New settings file called settings.js

var tempSettings = {
  "environment": "development",
[...]

Added to index.html:

<script src="settings.js"></script>

Service:

myApp.service("settings", function(){
  var settings = null;

  this.initialize = function() {
    settings = tempSettings;
    tempSettings = undefined;
  };

  this.get = function() {
    return settings;
  }

});

Update 1: I found a problem

Because the settings file is loaded async, it sometimes happens that a module tries to use the settings before they are loaded. I'll keep you updated on solutions. I have moved the settings into a service, that is definitely better.

Original question

When I google how to store environment settings in AngularJS apps, I come across options using Grunt or Gulp (and there's probably others as well), but to me this option seems much more obvious. Meaning that there's probably a good reason not to use it. Is this way of storing settings a bad idea?

I have in my app root a file called settings.json which looks something like this:

{
  "settingsFile": true,
  "environment": "development",
  "logLevel": "debug",
  "userApiBase": "http://localhost/covlelogin/web/api/",
  "oAuth": {
    "google":{
      "endpoint": "https://accounts.google.com/o/oauth2/auth",
      "clientId": "12345",
      "scope": "email profile",
      "state": "MyToken123",
      "redirectUri": "http://localhost/loginadmin/web/oAuthRedirect",
      "responseType": "code",
      "approvalPrompt": "force"
    }
  }
}

I then have a little bit in app.run that looks like this:

MyApp.run(function ($rootScope, $http) {
  //Load settings
  $http.get('settings.json').
      success(function (settings) {
        if (settings.settingsFile){
          $rootScope.settings = settings;
          console.log("Settings loaded");
        }else{
          console.log("Error loading settings. File may be corrupt.");
          //Additional error handling
        }
      }).
      error(function (data) {
        console.log("Error getting settings file.");
        //Additional error handling
      })
});

And now whenever I need a setting I can always go to $rootScope.settings.userApiBase or whatever. It makes sense to me, because all I have to do is to make sure settings.json is ignored on check-in. The whole method is really straight forward. Is there a flaw to this design?

like image 288
Coo Avatar asked May 28 '15 16:05

Coo


1 Answers

Try not to pollute the $rootScope Here as much as possible. Make a Settings service that handles the settings instead. Services are singleton objects so once you initialize the service, the settings will be available everywhere you inject the service.

MyApp.service("Settings", function($http) {

    var settings = null;

    this.initialize = function() {
        $http.get('settings.json').success(function (s) {
            if (s.settingsFile){
                settings = s;
                console.log("Settings loaded");
            } else {
                console.log("Error loading settings. File may be corrupt.");
                //Additional error handling
            }
        }).error(function (data) {
            console.log("Error getting settings file.");
            //Additional error handling
        })
    };

    this.get = function() {
        return settings;
    }

    return this;
});

And in MyApp.run:

MyApp.run(function (Settings) {
    Settings.initialize();
}

Then, whenever you want to access Settings in a controller or another service or something, simply call Settings.get() which will return your settings. Just make sure to inject the Settings service into anything that uses it (like I did in the second code block).

like image 145
roscioli Avatar answered Sep 21 '22 10:09

roscioli