Search code examples
javascriptangularjsdata-binding

Why is the binding in this application failing to update?


I have an array on my controller, which is displayed on the page with binding.I want to use a set function to update this value and display the new value on the page.

The whole idea behind this process, is that i'm dealing with data which i get from a database through an API call. The data arrives just fine, i just cant seem to make it available for further processing.

Im running Angularjs 1.6.4.

HTML Looks like this

<div ng-controller="CtrlName">
  <div ng-repeat="item in rows track by $index">{{item}}</div>
</div>

Controller like this

let rows = [1,2,3,4,5]

function getAllData() {
    qGetAllData().then(function(data) {
        console.log(data);
        setRows(data);
    }, function(errData) {
        console.log(errData);
    });
};

function qGetAllData()  {
    return $q(function(resolve, reject) {
        try {
        resolve(APISvc.get('PHP/API/ROUTE', {}));
        }
        catch {
            reject('fetching data failed');
        }
    });
};

function setRows(data) {
    console.log(typeof(data));
        //rows.push('test');
        //rows.push(data);
        rows = data;
};

angular.extend($scope, {
    getAllData : getAllData,
    qGetAllData: qGetAllData,
    setRows    : setRows,
    rows       : rows,
});

What happens is, when i call the page, i get the rows array displayed with the values 1 to 5 as it is innitially set. Then i fetch the data from the database and pass it into the setRows function. Nothing happens. I would expect the displayed data to change.

Wierdly enough, if i uncomment both push() commands, the data gets pushed and the view updates accordingly.

What am i missing here? I suspect digest cycles to be the culprint here but i'm not quite sure.


Solution

  • function setRows(data) {
        console.log(typeof(data));
            //rows.push('test');
            //rows.push(data);
            ̶r̶o̶w̶s̶ ̶=̶ ̶d̶a̶t̶a̶;̶
            $scope.rows = data;
    };
    

    The assignment statement is replacing the reference for the local variable but not the reference assigned to the $scope property.


    but why would the view be updated accordingly when i use rows.push()?

    When the code did:

    angular.extend($scope, {
        getAllData : getAllData,
        qGetAllData: qGetAllData,
        setRows    : setRows,
        rows       : rows,
    });
    

    The $scope property named rows is set to the same reference as the private variable named rows.

    $scope.rows == rows //the references are identical
    

    At this point they share the same contents. An operation such as .push() mutates that contents.

    When the code does the assignment

    rows = response.data;
    

    Then the private variable gets a new reference with new contents.

    $scope.rows !== rows
    

    The references are different. Their contents is different.

    The AngularJS watches $scope.rows which still references the old contents.