3

I have a function who get an array of objects by ajax using $http :

$scope.getArray = function(page) {
    return $http.get(page).then(function(data) {
        return data.data;
    });
};

I use it that way :

$scope.array = $scope.getArray('somepage');

This code works actually and I have the data I want on the view.

However, I want to add some data at the end of this array. I tried

$scope.addToArray = function(newItem) {
    $scope.array.push(newItem);
};

But that didn't work.

Any ideas how to do that ? Thanks.

0

2 Answers 2

1

It looks like you are mistreating the promise!

If you want to be able to fiddle with the data returned from getArray then you shouldn't assign the promise to your scope variable. Instead, change the way getArray works:

$scope.getArray = function(page) {
    var propertyAccessor = $parse(page);
    return $http.get(page).then(function(data) {
        page.assign($scope, data.data);
    });
};

Now when you call get array, it will load the data data into the data property and you will be able to modify that (once it has run for the first time)

$scope.getArray('somepage');

$scope.addToArray = function(page, newItem) {
   var propertyAccessor = $parse(page);
   propertyAccessor($scope).push(newItem);
}

$scope.addToArray('somepage', 'someValue');

I put a demo of this together here, it has both your original implemnenation (simulated using $q) and my working example.

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

4 Comments

That will be great if I had only one call, but I actually have three arrays who uses the same function, and I don't want multiple functions with same code.
I've updated the demo and example with a way of doing this. Is this what you mean?
Your answer is almost exactly that ; except I want to keep different names for the array, like $scope.array1 and $scope.array2. Probably by using eval, but will be ugly.
ok I have updated the code to do this. It uses $parse which allows you to set arbitrary objects, so you will see in the example the property being set is page.one, rather than just page1.
1

I chose a different approach to solving this. Not sure if it's better but I'll put it up here anyway.

(function(utility) {
    angular.module('app').

    service('data',['$q', function($q) {
      var deferred = $q.defer();
      var data = ['bla', 'bla'];

      //some async $http stuff being done resulting in deferred.resolve(data)

      utility.add = function(stuff) {
        data.push(stuff);
      };

      return deferred.promise;
    }]).

    service('dataService', [function() {

      return {
        add: function(data) {
          utility.add(data);
      };

  }]);
}({}));

Basically, any controller that are just interested in my array will have data injected while anyone who is potentially interested in adding stuff to my array will have dataService injected. I then create a closure over a utility object which contains an add function that pushes stuff into the array. This works (at least on 1.0.8) as the promise keeps the reference to the original array and the resolved value is actually updated when I change the original.

This way my controller is decoupled completely from the $http and does not have to concern itself with how data is fetched from the server, it just gets it handed over by declaring it as a dependency, and I have full control over how stuff gets added. My data is also cached since the service is a singleton while the controller is not.

Comments

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.