kiwi1342 kiwi1342 - 2 months ago 20
AngularJS Question

Share async data between controllers without making multiple requests

I'm trying to make a single

$http
request to get one of my JSON files and use the data across all my controllers.

I saw on egghead.io how to share data across multiple controllers, and I've also read this StackOverflow question: "Sharing a variable between controllers in angular.js".

However, the answers there don't use the
$http
module. When using
$http
, the controllers don't have the data to work on, and by the time the response is received it's already too late.

I then found the method
$q.defer
and this question on StackOverflow: "AngularJS share asynchronous service data between controllers"

The solution posted there works fine, BUT it has two issues:


  1. Each controller will trigger the
    $http
    request to obtain the same data already used in another controller; and,

  2. If I try to manipulate the data received I have a
    then
    function.



Below you can see my code:

controllers.js

'use strict';

/* Controllers */

function appInstallerListCtrl($scope, Data) {
$scope.apps = Data;
}

function appInstallerDetailCtrl($scope, $routeParams, Data) {
$scope.appId = $routeParams.appId;
$scope.apps = Data;
console.log($scope.apps); // <-- then function
console.log(Data); // <-- then function with $vv data returned but I can't access it

for (var i in $scope.apps) // <--- no way, baby!
console.log(i);
}


app.js

var app = angular.module('appInstaller', []);

app.factory('Data', function($http, $q) {
var defer = $q.defer();
$http.get('apps.json').then(function(result) {
defer.resolve(result.data.versions.version);
});
return defer.promise;
});

app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/app', {templateUrl: 'partials/app-list.html', controller: appInstallerListCtrl}).
when('/app/:appId', {templateUrl: 'partials/app-detail.html', controller: appInstallerDetailCtrl}).
otherwise({redirectTo: '/app'});
}]);


What I'd like to have is that when launching the app, the
$http
request will be performed and the response will be used throughout the app across all controllers.

Thanks

Answer

Since you are using a promise, to access the data returned by promise use the callback syntax

function appInstallerDetailCtrl($scope, $routeParams, Data) {
  $scope.appId = $routeParams.appId;
   Data.then(function(returnedData) {
        $scope.apps=returnedData;
        console.log($scope.apps);
        for (var i in $scope.apps)
           console.log(i)   
   });   
}

Make sure this

defer.resolve(result.data.versions.version);

resolve returns array, for the above code to work. Or else see what is there in data and ajust the controller code.

Comments