Reputation: 479
I have a simple AngularJS application. I am now trying to implement a L10n* mechanism into it. For that I have service which loads a strings file and returns an array of key-values. These values are later put into views and controllers.
To keep stuff straight and simple I assign the return array to $rootScope so that every controller/view has access to the same list. I am doing it from the angular.module(...).run() function
And this is where the problem starts - some controllers can access the $rootScope object, whilst some other cant (and return undefined). I suspect this is because the promise is not resolved in time before the first few controllers are loaded.
The question is - how do I make the controllers wait for the resource to be loaded?
Auxiliary question - Why can GenericListController use $scope.localisation but ListController cant?
service declaration
app.factory("StringsTranslationService", function($http) {
var getData = function(locale) {
return $http({method:"GET", url:'public/resources/strings_'+locale+'.txt'}).then(function(result){
return result.data[0];
});
};
return { getData: getData };
});
load data from service to $rootScope in app.js
app.run(function($rootScope,StringsTranslationService) {
var myDataPromise = StringsTranslationService.getData('en');
myDataPromise.then(function(result) {
$rootScope.localisation=result;
});
});
Finally try to use in controller.js:
var app=angular.module('myApp');
app.controller('ListController', function ($scope, $controller){
console.log($scope.localisation["_NAME_"]);
angular.extend(this, $controller('GenericListController', {$scope: $scope}));
});
The most interesting fact is that GenericListController is also using the same $scope.localisation array and it has not problems with it!
The load order is:
Upvotes: 0
Views: 2120
Reputation: 3787
Instead of copying yr results to $rootScope, you should directly read from service.
why ? Yr $rootScope lives throughout yr application life, it sits right above all yr controller's scope, so its better to keep it lightest.
code :
app.factory("StringsTranslationService", function($http,$q) {
var StringsTranslationService={};
var data='';
var dataReady=false;
StringsTranslationService.getData = function (locale) {
var deferred= $q.defer();
$http({
method:"GET",
url:'public/resources/strings_'+locale+'.txt'
})
.success(function(result){
deferred.resolve(result.data[0]);
})
.error(function(error){
deferred.reject(error);
})
return deferred.promise;
};
return StringsTranslationService;
});
Update yr app.run
app.run(function(StringsTranslationService){
//call service & read data
StringsTranslationService.getData('en')
.then(function(data){
StringsTranslationService.data=data;
StringsTranslationService.dataReady=true;
//if you really want it add to rootScope
//$rootScope.localisation=data;
},
function(error){
//handle error here
})
});
Inside yr controller check if data is ready & then read
app.controller('ListController', function ($scope, StringsTranslationService){
if(StringsTranslationService.dataReady===false){
$scope.loading=true;
}
else {
$scope.loading=false;
$scope.data=StringsTranslationService.data;
}
});
This way you will only do a single call to fetch data & it will b available across app.
Upvotes: 1