Fluxionsdx Fluxionsdx - 4 months ago 8
Javascript Question

angular - I have an element in the view bound to a variable in a service, but the view is not getting updated when the service is updated

I have a variable appList = [1,2,3] that is stored in a service. I import appList into the controller and bind it to the view in a list. I have a function modifyAppList in the controller that calls a function of the same name in the service. This function is called with a button click in the view, and doing so definitely modifies the value in the service, as you can see with the console logs. I am very confused, because the view never updates even though the value in the service changes. If someone could take a look at the code and offer an explanation that would be much appreciated.

NOTE If you just change the contents of modifyAppList() to

appList[0] = 5; appList[1]= 6; appList[2]=7;
it will work as I expect. Something funny is happening when I assign appList to a new array inside of modifyAppList()



angular.module('app', []);

angular.module('app')
.factory('appService', appService)

function appService(){
var appList = [1,2,3];
var modifyList = [5,6,7];
var modifyAppList = function(){
console.log("At the beginning of modifyAppList: ", appList)
appList = [];
console.log("After appList=[] : ", appList)
for(var i = 0; i < 3; i++){
appList.push(modifyList[i]);
}
console.log("After modification: ", appList)


}
return {
getAppList : function(){
return appList;
},
modifyAppList : modifyAppList
}
}

angular
.module('app')
.controller('appCtrl', appCtrl)

appCtrl.$inject = ['appService'];
function appCtrl(appService){

this.appList = appService.getAppList();
this.modifyAppList = function(){
appService.modifyAppList();
var testList = appService.getAppList();
console.log("After modification, and calling getList() : ", testList)
}
}

<body ng-controller="appCtrl as vm">

<ul>
<li ng-repeat="num in vm.appList" ng-bind="num"></li>
</ul><br>
<button ng-click="vm.modifyAppList()">modifyAppList()</button>


<script src="controller.js"></script>
<script src="service.js"></script>


</body>




Answer

When the code does appList = [];, it replaces the object reference with a new object reference. The object reference in the controller still points to the old array. (appList = []; literally means appList = new Array();)

To preserve the old reference, use angular.copy:

function appService(){
    var appList = [1,2,3];
    var modifyList = [5,6,7];
    var modifyAppList = function(){ 
        angular.copy(modifyList, appList);
    }
    return {
        getAppList : function(){
            return appList;
        },
        modifyAppList : modifyAppList
    }
}

From the Docs:

angular.copy

Usage

angular.copy(source, [destination]);

Creates a deep copy of source, which should be an object or an array.

  • If a destination is provided, all of its elements (for arrays) or properties (for objects) are deleted and then all elements/properties from the source are copied to it.

--AngularJS angular.copy API Reference

Comments