user2994560
user2994560

Reputation: 1309

AngularJS $http use response in multiple controllers

I have an app where I am loading a bunch of albums in one partial and then when a user clicks on each individual album, they get details for the album like songs, etc. Right now I am pulling the data from database but doing it twice, once in ProjectsCtrl to show all the albums and then again in ProjectsDetailCtrl for the individual album info. I feel like there is a faster way to do this, but can't figure out how to save the data from the first time to use again in the 2nd controller

(function() {
    var app = angular.module('chp', ['ngRoute', 'projectControllers']);

    app.config(['$routeProvider',
      function($routeProvider) {
        $routeProvider.
          when('/', {
            templateUrl: 'partials/directory.html',
            controller: 'ProjectsCtrl'
          }).
          when('/album/:slug', {
            templateUrl: 'partials/album.html',
            controller: 'ProjectDetailCtrl'
          }).
          otherwise({
            redirectTo: '/'
          });
      }]);

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

    projectControllers.controller('ProjectsCtrl', ['$scope', '$http',
      function ($scope, $http) {
        $http.get('/get_albums').success(function(albums) {
            $scope.projects = albums;
            $scope.filters = { };
        });
      }]);



    projectControllers.controller('ProjectDetailCtrl', ['$scope', '$http', '$routeParams', '$sce',
      function($scope, $http, $routeParams, $sce) {


        $http.get('/get_albums').success(function(albums) {
            $scope.projects = albums;

            for(var i = 0; i < $scope.projects.length; i++) {
                if($scope.projects[i].slug === $routeParams.slug){
                    $scope.album = $scope.projects[i];
                    $scope.albumIdx = i;
                    break;
                }
            }    

            $scope.project = albums[$scope.albumIdx];

            $scope.showVideo = function(id) {
                var videoCode = $(this)[0].song.video;
                // videoCode = '<iframe width="560" height="315" src="'+video+'" frameborder="0" allowfullscreen></iframe>';
                $('#myModal .flex-video').html(videoCode);
                $('#myModal .track-number').html('<span style="color: #f86081; display: inline-block; margin-right: 4px;">' + ($(this)[0].$index+1) + '.</span> ' + $(this)[0].song.title);
                $('#myModal').foundation('reveal', 'open');
            }

        });

    }]);
})();

Upvotes: 4

Views: 861

Answers (4)

user4616903
user4616903

Reputation:

Yep, service or factory would be fine for this case. You could also store that previously entered data in local storage for example using that service. Basically it's better way for improvements in future.

As a simpler way, you can simply use $rootScope. It's available in all your controllers it you wish so.

Just need to inject it into controller or in the app itself.

app.controller('myCtrl', function($rootScope){
    $rootScope.myStoredValues = {...};
});

or

app.run(function($rootScope){
    $rootScope.root = $rootScope; 
    $rootScope.myStoredValues = {...};
    // this way you don't need to inject it into controller, 
    // it will be available there via $scope.root.myStoredValues
});

Upvotes: 1

praga2050
praga2050

Reputation: 773

app.factory('ProjectService', function ($http) {
  var projects = []
  return{

    getProjectList: function(){
      $http.get('/get_albums').success(function(albums) {
        projects = albums;
      });
    },

    getProject: function( id ){
      // here you can select the already existing project from the above list "projects" by using the Id passed
    }

  }

});

You can include this service in controllers and use them to get list of albums and single album

Upvotes: 0

Pedro Affonso
Pedro Affonso

Reputation: 1676

I would go with either injecting $rootScope in both controllers

myApp.controller('controllerA', function($rootScope){
    $rootScope.sharedData = {album: ...};
    ...
});

Or creating a value and injecting it in both controllers to pass this data around:

myApp.value('myValues', '{sharedData: {}}');
myApp.controller('controllerA', function(myValues){
    myValues.sharedData.album = ...
    ...
});

This is basically the same question, and has a good answer and comments:

Best way to pass data between ngRoute controllers (from one view to the next)

Upvotes: 1

JLRishe
JLRishe

Reputation: 101662

If $http.get('/get_albums') produces all of the data that you need for both controllers, then it sounds like you just need to use caching:

$http.get('/get_albums', { cache: true })....

Use that in both controllers and you'll only be hitting the server once.

Preferably, this would be placed in a factory so that the data retrieval logic is only in one place, but that's not an absolute requirement.

Upvotes: 5

Related Questions