2

I have an AngularJs application in which I want to load the messages and application version at the very beginning and save them in local storage, then use them in the controllers afterwards. What I have for now is a service call in each of the controllers (which are three for now):

 localisationService.getMessages($scope.language).then(
            function (data) {
                $scope.messages = data;
                //initialze kendo grids with the messages etc.
                //all of the controller logic is here
 }

I want to take the application version only once and store it there. I don't have to check the version each time, right (In case a new message was added in the new version)?

I found a suggestion to use $routeProvider but my application is not a SPA. So I need other ideas/suggestions. Your help will be greatly appreciated.

van
  • 367
  • 4
  • 13
  • 1
    If your application is not an SPA why are you using angular? Infact, why aren't you rewriting it to be an SPA? – Jodrell Nov 20 '17 at 12:22
  • I'm planning to do that in some time, I just have to get this working for now. – van Nov 20 '17 at 12:24
  • If you change pages the browser will reload everything, that is how browsers work. – Jodrell Nov 20 '17 at 12:26
  • 1
    Perhaps you can do something with the Web Storage API https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API – Jodrell Nov 20 '17 at 12:28
  • I'm using localStorage and I want to make the http get for the messages and version before using the controller. Something like app bootsrapping – van Nov 20 '17 at 12:30
  • You miss the fact that in your case the language is dynamic. If you load the messages before app initialization, you're unable to change the language later, aren't you? – Estus Flask Nov 20 '17 at 14:27
  • @estus my idea was to load the messages on initialization and then each time when the language changes. I also want to keep the messages version and also get the messages again when the app version is different than the local storage version – van Nov 20 '17 at 14:48
  • 1
    Then you likely want to go for a solution that is capable to handle both scenarios, i.e. router resolver. – Estus Flask Nov 20 '17 at 14:50

1 Answers1

3

As the question already mentions, this is usually solved with router resolvers because the initialization of route controllers can be naturally postponed this way. Since AngularJS router uses hashbang mode by default, it can be used with non-SPA (and can be recommended for complex non-SPA widgets):

resolve: { 
  l10n: (localisationService) => {
    return localisationService.getMessages(localisationService.language)
  }
}

The result can be optionally cached to avoid requests when language is unchanged.

Additionally, route definitions can be processed to add common local dependency (l10n) to all routes automatically.

The problem with global services that should be asynchronously initialized can also be solved in Angular 2 and higher with asynchronous bootstrapping and APP_INITIALIZER provider. AngularJS doesn't have this capability. As this answer explains, in order to implement this in AngularJS there should be two applications, where initializer application loads all necessary data and then bootstraps main application:

angular.module('app', [/* ... */]);

angular.module('appInitializer', [])
.factory('loader', ($http) => {
  return $http.get('...').then((result) => result.data);
})
.factory('initializer', (loader, $document) => {
  return loader.then((data) => {
    angular.module('app').constant('l10n', data);

    $document.ready(() => {
      angular.bootstrap($document.find('body'), ['app']);
    });
  });
});

angular.injector(['ng', 'appInitializer'])
.get('initializer')
.catch((err) => console.error(err));

Considering that in original code the language is defined dynamically with $scope.language, second option (initializer application) is not applicable, and this should be performed with first option (route resolvers).

Estus Flask
  • 206,104
  • 70
  • 425
  • 565