2

I want multiple controllers to be able to update a single view attached to one controller using a factory with $http.

My list view:

<div class="list" ng-repeat="image in images" ng-controller="controller1">
   <div lass="item"><img src="{{image.url}}" /></div>
</div>

Service:

.factory("imageService", function($http) {
  return {
    getImages: function() {
      return $http({
        method: "get",
        url: "http://example.com/images",
        params: { user: window.localStorage['user_id'] }
      })
    }
  }
});

Controller 1:

.controller('controller1', function($scope, imageService) {
   window.localStorage['user_id'] = '101';
   var handleSuccess = function(data, status) {
       $scope.images = data;
   };
   imageService.getImages().success(handleSuccess);
})

This all works. When the app is loaded, the list immediately is populated with a list of images for user '101'.

In another controller, I want to be able to switch users and automatically re-poupulate the image list in the view from controller 1 with new images.

Controller 2:

.controller('controller2', function($scope, imageService) {
   window.localStorage['user_id'] = '202';
   imageService.getImages();
})

So controller 2 will run getImages() and I can see the $http request working via chrome dev tools / XHR. And I know why the list view attached to controller1 is not populating, but I dont know how to make it populate. I have tried moving the success callback into the service and setting a 'images' property on the service and a $scope.images in controller1, but no luck there.

How can I force the new list of images into the view attached to controller 1?

3
  • You could emit an event from the rootScope to the controller and the listener for the emit handles loading the images from the imageService. Commented Aug 5, 2015 at 14:40
  • @tafoo85 Is using $rootScope definitely required to get the image list updated? Commented Aug 5, 2015 at 14:48
  • Nah, it was off the top of my head quick two second solution. That other guy's idea is better. Commented Aug 5, 2015 at 14:57

2 Answers 2

3

You should just manage a list into your service that you will bind to your controller1 :

.factory("imageService", function($http) {
    var service = {};
    service.images = {};
    service.images.list = [];
    service.getImages = function(userId) {
      window.localStorage['user_id'] = userId;
      return $http({
        method: "get",
        url: "http://example.com/images",
        params: { user: userId }
      }).success(function(data){
          service.images.list = data
      });
    }

  //at the initialization of the service, you launch the getImages once with the localStorage value.
  service.getImages(window.localStorage['user_id']);

  return service;
});

Then you can bind it like this in your controllers :

.controller('controller1', function($scope, imageService) {
   $scope.images = imageService.images;
   //then access it in the view with images.list
   imageService.getImages(101);
})

.controller('controller2', function($scope, imageService) {
   $scope.images = imageService.images;
   //then access it in the view with images.list
   imageService.getImages(202);
})

Note that using a sub object (images.list instead of images) is important.

If you want some more precise informations about why this sub object is needed you can read this answer on this subject

Hope it helped.

Sign up to request clarification or add additional context in comments.

5 Comments

So in the view, ng-repeat="image in images.list". This seems to work well. Let me test.
@lilbiscuit How is the integration doing ? Feel free to ask if you need some help. That's exactly how the ng-repeat will look like.
@lilbiscuit Btw, why don't you use a var with your get function instead of using the local storage ?
@Okazzari - I use localStorage to preserve the user selection (this is a mobile hybrid app).
@lilbiscuit i'm not sure i understood your question but you can manage the user_id local storage into the service. I'll update the answer to show how.
0

I think you can just use one controller. At some time point, say, a user clicks some button, reload the image lists and re-render the view to show the list.

For example, make the factory like:

.factory("imageService", function($http) {
  return {
    getImages: function(userId) {
      return $http({
        method: "get",
        url: "http://example.com/images",
        params: { user: userId }
      });
    }
  };
});

And in the controller:

.controller('imageController', function($scope, imageService) {

   function refreshImages (userId) {
     imageService.getImages(userId).success(function(data) {
       $scope.$apply(function () {
         $scope.images = data;
       });
     });
   }

   refreshImages('101');
   $scope.loadImages = function (userId) {
     refreshImages(userId);
   };
});

4 Comments

I need to be able to update the list from within multiple controllers.
Well, if the two controllers shares the same scope, you need to call $scope.$apply after getting new list of images.
I still cannot imagine your scenario. Controllers should not share such kind of logic. You either extract to service/factory or directive.
The scenario is that each view in my app has its own controller. One view / controller displays the list of images. The other view/controller displays a list of users. Select a user in controller2 view, and see the resulting images for the selected user controller1 view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.