0

I'm having a problem getting at values in my service from the controller. My service looks like this:

angular.module('someApp').factory('someSvc', SomeSvc);

function SomeSvc($http) {
    var colors = [];
    function loadColors() {
        return $http.get('SomeApi/GetColors')
            .then(function (result) {
                //colors = result.data.colors;//<-this doesn't work
                //angular.copy(result.data.colors, colors);//<-this works
            });
    }
    return {
        loadColors: loadColors,
        colors: colors
    };
}

Then my controller might make a call like this:

someSvc.loadColors().then(function(){vm.colors = someSvc.colors;});

So, when I debug, if I set a breakpoint in the controller where the assignment to vm.colors is made, the colors property exposed on the someService object has just an empty array or any array with the expected values depending on which of the two commented-out lines I use in the service.

If I set a breakpoint in the service where the assignment to colors is made, the variable colors always has the expected values (e.g., let's say ["red", "yellow", "green"] is what comes back from the http call). So I can watch the controller trigger the http call, watch the value come back and get assigned to colors in the service, but then the controller just sees an empty array unless I do that angular.copy call.

Also, interestingly, if I change the service's return statement to look like this:

return {
    loadColors: loadColors,
    colors: function() {return colors;}
};

and then in the controller say vm.colors = someSvc.colors(); then that works just fine as well.

Why is this? Why isn't that array getting passed through?

UPDATE: I've found that instead of the angular.copy() line, I can alternatively do this, and everything works as expected:

for (var i = 0; i < result.data.colors.length; i++) {
    colors[i] = result.data.colors[i];
}

It seems to be that ASSIGNING the object is a problem, while modifying it is ok? Why is that?

ctb
  • 1,212
  • 1
  • 11
  • 24

2 Answers2

1

This might work for ya. Guessing it's just a pointer issue maybe?

angular.module('someApp')

.factory('someSvc', function($http)
{
  return {
    colors: [],
    loadColors: function()
    {
      var self = this;

      return $http.get('SomeApi/GetColors').then(function (result) 
      {
        self.colors = result.data.colors;
      });
    }
  };
});
gmustudent
  • 2,229
  • 6
  • 31
  • 43
  • The key is var self = this; - It's ensuring that your pointing to the right colors object when the data comes back. – gmustudent Sep 23 '16 at 19:29
  • Yes, but why isn't it pointing to the right object without the this reference? And why does it make a difference whether I do an assignment operation or update the reference (like with the angular.copy() or manual for loop options)? – ctb Sep 23 '16 at 20:51
  • No idea! Maybe angular.copy traverses the tree to find color? Maybe the fact that you're passing it to that fn helps it find what you really want better then when you're just writing it out? I really don't know man, I don't write factories the way you demo'd it so I couldn't really tell ya why it's acting funky! Just tryin to point you in the right direction! – gmustudent Sep 23 '16 at 20:56
  • You definitely did, just eats at me when I don't really understand the why of a thing. Incidentally, what DO your factories look like? Are mine wrong or weird in some way? – ctb Sep 23 '16 at 21:33
  • @ctb They look exactly how I posted! I wouldn't steer ya in the wrong direction! – gmustudent Sep 23 '16 at 21:34
0

At the time you're calling return in your Factory, someSvc.colors is just the empty array - and the value is returned. Since Angular providers in general attempt to run only once, in future it doesn't actually check someSvc.colors again - just returns the initial value.

Wrapping it in a function means it runs the function every time, so it fetches the updated value.

Simon Poole
  • 493
  • 1
  • 6
  • 15
  • If that were the case, why would the other line make it work: `angular.copy(...)` – ctb Sep 23 '16 at 18:33