2

I have an object in a service which is loaded asynchronously from a PouchDB.

I cannot in any way get the view to update as the service object is updated. I have followed many tutorials, answers, plnkrs, gists and just can't get it.

See http://plnkr.co/edit/jtFNs5FbrDBLlyZ5TATn?p=preview for my example. Any ideas?

Controller code:

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

hubApp.service('objService', function($q, $timeout) {
  var objects = [];
  this.getObjects = function() {
      var data = $q.defer();
      var foo = data.promise;
      $timeout(function() {
        data.resolve([{"name": "first"},{"name": "second"}]);
      }, 2);
      foo.then(function(objs){
        console.log(objs);
        angular.forEach(objs, function(obj) {
          objects.push(obj);
        })
        console.log(objects);
      });
  }
  this.getObjects();
});

hubApp.controller('ListCrtl', ['$scope', 'objService',  
  function ($scope, objService) {
    $scope.objects = objService.objects;
  }
]);

View code:

  <body ng-controller="ListCrtl">
    <p ng-repeat="item in objects">Hello {{item.name}}!</p>
  </body>

Thanks.

julian
  • 63
  • 1
  • 6
  • `var objects` is not same as `this.object`. Why cant you call `getObjects` and chain it through the promise. How will you make sure that by the time the controller is invoked the promise would have resolved. – PSL Aug 19 '14 at 15:11
  • No, that is me trying to figure things out. Using this.objects results in an error in the .push code, although the .push was again me trying to troubleshoot. – julian Aug 19 '14 at 15:13
  • Here http://plnkr.co/edit/uZxQ5L?p=preview – PSL Aug 19 '14 at 15:15
  • Isn't the issue the service should return the promise and then the controller should handle the THEN. And when the THEN completes update the scoped collection (ie. $scope.objects). – JerryKur Aug 19 '14 at 15:19
  • But what i would do:- http://plnkr.co/edit/pBlAY5?p=preview – PSL Aug 19 '14 at 15:20
  • @JerryKur yes that is the right way to do.. Here it will work since `objects` is initialized and same array reference is modified... scope object will also get modified. Since there is `$timeout` it will trigger digest cycle, in the real case with a non angular async call, it would need a digest cycle to be run. I would use promise based approach. – PSL Aug 19 '14 at 15:21
  • Thank you so much @PSL, plnkr works, just need to test it out in my app now. – julian Aug 19 '14 at 15:21
  • @JerryKur the reason I'm trying to do it this way is that another controller updates that object and I need to keep the view of the first controller updated. – julian Aug 19 '14 at 15:22
  • @user2124304 you should try to use the second plnkr. And if another controller updates the object, then use eventing to notify.. the other controller to refresh the data. So basically your service will have an updatemethod and a getmethod and they can notify each other through eventing/ – PSL Aug 19 '14 at 15:22
  • 1
    Thanks PSL. That is what I do in my code. But, it always felt like it was a little bit like splitting getting the data into two parts. The service would do the actually fetching of the data, but the controller would handle the mapping. But, I suppose this is correct from a separation of concerns viewpoint. – JerryKur Aug 19 '14 at 15:24
  • user2124304. I understand. I usually separate objects that I share between controllers into a separate service factory that is injected into the controllers that are interested in the data. I do that separate from the actually fetching of the data. This is because sometimes the shared data changes because of non i/o related reasons in some controller, ex manually adding an item onto a collection. This video is similar to what I do, https://egghead.io/lessons/angularjs-sharing-data-between-controllers. However, I return a shared data object with each value as a property. – JerryKur Aug 19 '14 at 15:31
  • @PSL okay, sounds like this could be a better option. I don't know anything about notifying via eventing, could you recommend some reading please? – julian Aug 19 '14 at 15:35
  • @JerryKur thanks, I'll take a look at the video. Any code samples would be gratefully received, I've seen so many recommendations on how to approach this but this thread is the first time I've actually got it working! Thanks both – julian Aug 19 '14 at 15:36
  • You could look for `$broadCast`, `$emit`, `$on` etcc. I have an answer and the last solution is a pub sub that i use personally to avoid injecting rootscope in my controllers.. http://stackoverflow.com/questions/25274563/angularjs-communication-between-directives/25274665#25274665 – PSL Aug 19 '14 at 15:37
  • @JerryKur just watched the video. What I'm missing is how to update that shared data by using a promise to fetch data from outside of angularjs. Any ideas? – julian Aug 19 '14 at 15:40
  • Updating the data is simply assigning the shared value a new value in the .Then() handler. That is sharedData.myProp = newValue; And in the shared data factory we have { factoryValues={}; factoryValues.myProp=null; return factoryValues;} And to notify any other controllers to fetch the updated from the shared data factory use methods PSL mentioned and references. – JerryKur Aug 19 '14 at 18:17

0 Answers0