Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularjs Ionic and global variables: best practice to make a variable available globally

I am new to Angular/Ionic. Before using Angular/Ionic, at the launch of my app, I was checking if we were under Phonegap or a browser using and storing this information in a global boolean variable and then checking if the app was online or offline and storing it to a global variable too, like this :

var isPhoneGap;
var connectionStatus;
isPhoneGap = checkIfPhoneGap();

//later in the code :

connectionStatus = checkIfOnline();

function checkIfPhoneGap() {
    var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1; // && document.URL.indexOf( 'file://' );
    if ( app ) {
        return true;
    } else {
        return false;
    }
}
function checkIfOnline() {  
    if ( isPhoneGap ) {
        if (checkConnection() == "none" ) {
            connectionStatus = 'offline'; 
        } else {
            connectionStatus = 'online';
        }
        function checkConnection() {
            var networkState = navigator.network.connection.type;
            var states = {};
            states[Connection.UNKNOWN]  = 'Unknown connection';
            states[Connection.ETHERNET] = 'Ethernet connection';
            states[Connection.WIFI]     = 'WiFi connection';
            states[Connection.CELL_2G]  = 'Cell 2G connection';
            states[Connection.CELL_3G]  = 'Cell 3G connection';
            states[Connection.CELL_4G]  = 'Cell 4G connection';
            states[Connection.NONE]     = 'No network connection';
            //console.log('Connection : ' + Connection);
            //console.log('Connection type: ' + states[networkState]);
            return networkState;
        }
    } else {
        connectionStatus = navigator.onLine ? 'online' : 'offline';
    }
    return connectionStatus;
}

Now I would like to do the same with Angular/Ionic, I understand that I have to use a "Service". But is it the best way to make this information available through all the code ?

I am doing the following, but is it the "best practice" ?

in index.html :

<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>

in services.js :

angular.module('SnowBoard.services', [])

.factory('isPhoneGap', function() {

    var appp = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1; // && document.URL.indexOf( 'file://' );
    if ( appp ) {
        return true;
    } else {
        return false;
    }

})

;

in app.js :

angular.module('SnowBoard', ['ionic', 'SnowBoard.controllers', 'SnowBoard.services'])

.run(["isPhoneGap","$ionicPlatform", function(isPhoneGap, $ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleDefault();
    }
  });

  //CHECK IF ONLINE
  connectionStatus = checkIfOnline(isPhoneGap);

  //DEBUG
  //var debugOptionUseLocalDB=0;
  //updateProDB(connectionStatus, debugOptionUseLocalDB);
}])
.config(function($stateProvider, $urlRouterProvider) {
//...all state configurations
})
.config(function($stateProvider, $urlRouterProvider) {
//...
});

This works for now, but I need the boolean isPhoneGap to be available everywhere I need it (almost everywhere in my app).

Can you converge to the best practice to do this ?

Thanks

like image 318
Louis Avatar asked Nov 23 '14 21:11

Louis


People also ask

Is it good practice to use global variables?

Using global variables causes very tight coupling of code. Using global variables causes namespace pollution. This may lead to unnecessarily reassigning a global value. Testing in programs using global variables can be a huge pain as it is difficult to decouple them when testing.

Is it better to use more number of global variables?

The value of a global variable can be changed accidently as it can be used by any function in the program. If we use a large number of global variables, then there is a high chance of error generation in the program.

Is it better to use local or global variables?

So, by using a local variable you decrease the dependencies between your components, i.e. you decrease the complexity of your code. You should only use global variable when you really need to share data, but each variable should always be visible in the smallest scope possible.

Why should we avoid global variables in JavaScript?

Avoid global variables or minimize the usage of global variables in JavaScript. This is because global variables are easily overwritten by other scripts. Global Variables are not bad and not even a security concern, but it shouldn't overwrite values of another variable.


2 Answers

You should not set variables using $rootScope, and try to refrain from using $scope as much as possible. Using LocalStorage is okay, but this data will persist. I would recommend setting up a factory to store and retrieve variables using SessionStorage. SessionStorage is tied to the tab you have open, so the data is gone when it is closed.

This is one of my session storage services. I throw $cookieStorage in case local storage isn't available. Also, localStorage can only store strings. This is why you will see me converting objects and arrays to and from JSON as needed. After injecting sessionService, I need only call sessionService.store(name, data) to store a session variable or sessionService.persist(name, data) to store persistent data i.e. userName if "Remember Me" is checked. :

.service('sessionService', ['$cookieStore', function ($cookieStore) {
    var localStoreAvailable = typeof (Storage) !== "undefined";
    this.store = function (name, details) {
        if (localStoreAvailable) {
            if (angular.isUndefined(details)) {
                details = null;
            } else if (angular.isObject(details) || angular.isArray(details) || angular.isNumber(+details || details)) {
                details = angular.toJson(details);
            };
            sessionStorage.setItem(name, details);
        } else {
            $cookieStore.put(name, details);
        };
    };

    this.persist = function(name, details) {
        if (localStoreAvailable) {
            if (angular.isUndefined(details)) {
                details = null;
            } else if (angular.isObject(details) || angular.isArray(details) || angular.isNumber(+details || details)) {
                details = angular.toJson(details);
            };
            localStorage.setItem(name, details);
        } else {
            $cookieStore.put(name, details);
        }
    };

    this.get = function (name) {
        if (localStoreAvailable) {
            return getItem(name);
        } else {
            return $cookieStore.get(name);
        }
    };

    this.destroy = function (name) {
        if (localStoreAvailable) {
            localStorage.removeItem(name);
            sessionStorage.removeItem(name);
        } else {
            $cookieStore.remove(name);
        };
    };

    var getItem = function (name) {
        var data;
        var localData = localStorage.getItem(name);
        var sessionData = sessionStorage.getItem(name);

        if (sessionData) {
            data = sessionData;
        } else if (localData) {
            data = localData;
        } else {
            return null;
        }

        if (data === '[object Object]') { return null; };
        if (!data.length || data === 'null') { return null; };

        if (data.charAt(0) === "{" || data.charAt(0) === "[" || angular.isNumber(data)) {
            return angular.fromJson(data);
        };

        return data;
    };

    return this;
}])

$cookieStore is part of ngCookies. Make sure you have angular-cookies.js included and load ngCookies as you would any module. Angular ngCookies

like image 81
Owen Avatar answered Oct 21 '22 02:10

Owen


First off, I'm pretty new to both Ionic and Angular, however I had the same problem with my web app Angular and I have done following to get it working

  1. assign variables to $rootScope, that way it's visible to all the controllers

  2. assign variables to $scope , which is visible by current context. Ex: controller and the html pages uses that controller

  3. localStorageService, because this will hold the values even after user refreshes the page.

Again please note, this is what I did in my Angular web app and might not be the best practices, but I hope you get the idea.

like image 24
sameera207 Avatar answered Oct 21 '22 01:10

sameera207