3

I have 2 array objects both initialized with $http response but when I try to add(push) in one array, it gets added into both.

I tried below code:

Controller:

myApp.controller("abc", function($scope, lastday_data){
    $scope.objectiveData = [];
    $scope.doneData = [];

    // call service & get data from server
    lastday_data.getData().then(function(success){
        $scope.objectiveData = success;
        $scope.doneData = success;
        $scope.$digest();  // *---> $digest() used*
    },function(error){
        $scope.objectiveData = null;
        $scope.doneData = null;
    });

    // add task done
    $scope.addTaskDone = function() {
        var p = {"id": 101, "name": "testadd", "check": true};
        $scope.doneData.push(p);
        $scope.textDone = "";
    }
});

Service: -- get data from the server

myApp.service("lastday_data", function($http){
    this.getData = function() {
        return new Promise(function(resolve, reject){
            $http({
                method: 'GET',
                url: 'http://localhost/task/index.php/v1/example/users'
            }).then(function (response) {
                if(response.status)
                    resolve(response.data);
                else
                    reject();
            },function (error) {
                reject();
            });
        });
    }
});

Problem: when I try to call controller's addTaskDone() method, this method add one object in doneData array but this object get added in objectiveData also.

2 Answers 2

3

Basically the problem is objectiveData & doneData $scope variables are holding same memory location. So changing any of the value would make changes in all of three value success, objectiveData and doneData.

So basically you should make sure that while assigning a one variable with multiple values, create a clone of that success variable and keep then assign that variable to desired variable.

In angularjs there is angular.copy method exists, which will help you to create clone of an object with new memory location. That will ensure that the new variable will point to different memory location.

Controller:

$scope.objectiveData = angular.copy(success);
$scope.doneData = angular.copy(success);

Bonus: It clearly seems that you have wrong implementation of service, where you're creating an promise explicitly that's the reason why you had to call $digest inside your .then success callback. It means that you're creating an cases where you have to run digest cycle manually since code will be running outside angularjs context. Rather you should return the existing $http promise like below, and remove $scope.$digest() from you code which isn't needed at all.

Service

myApp.service("lastday_data", function($http) {
  this.getData = function() {
    return $http({
      method: 'GET',
      url: 'http://localhost/task/index.php/v1/example/users'
    }).then(function(response) {
      if (response.status)
        return response.data;
      else
        return $q.reject('Problem retrieving data');
    }, function(error) {
      return $q.reject(error);
    });
  }
});
Sign up to request clarification or add additional context in comments.

1 Comment

This should be the accepted answer. It is the more angular way and also corrects the $digest issue.
0

The problem

Both $scope.objectiveData and $scope.doneData are referencing the same variable success, so if you change one, the other one is changed too.

Solution

Make $scope.objectiveData and $scope.doneData reference independent variables by getting independent copies of success. You can use for this

Plain JavaScript

AngularJS builtin functions

Other tricks

$scope.doneData = JSON.parse(JSON.stringify(success));

So instead of

$scope.objectiveData = success;
$scope.doneData = success;

Do (or any other of the previous alternatives)

$scope.objectiveData = success.slice(); // get a copy of success
$scope.doneData = success.slice(); // get a copy of success

1 Comment

thanks for this, I didn't know about Array.from. So much new es6 to learn, so little time.

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.