Why does angularJs update all array / hashmap elements if only one has changed?
I have a simple hashmap and a simple method that displays the status in text, but when I only update 1 user status, they all update (the function is called for all users). Is there a way to update just one item and not all of them?
Sample code is here, just see what happens in the console when you click the Change Status button.
HTML:
<div ng-app="myApp">
<div ng-controller="Ctrl">
<div class="user-panel" ng-repeat = "(id, user) in _users">
Status:
<span class="user-status{{user.status}}">
{{getStatusInText(user.status)}}
</span>
<hr>
<div class="toLeft">(<b>{{id}}</b>) {{user.name}}</div>
<div class="toRight">
<button ng-click="changeUserStatus(id, '1')">Change Status</button>
</div>
<div class="clear"></div>
</div>
</div>
</div>
AngularJS:
var app = angular.module('myApp', []);
function Ctrl($scope) {
$scope._users = {"123":{"name":"test","status":"0"}, "124":{"name":"test2", "status":"0"},"125":{"name":"test2", "status":"0"}};
$scope.getStatusInText = function(status) {
console.log("CALLED: " + status);
return (status === "1") ? "online" : "offline";
}
$scope.changeUserStatus = function(uId, status) {
$scope._users[uId].status = status;
}
}
And the fiddle for the example above:
another example with iteration, which is called each time using the getStatusInText function.
source to share
Updated example : http://jsfiddle.net/ztVnj/5/
The theory is here :
Move the expensive operation outside of the hashmap and manually configure the update. As mentioned, if the hash is changed at all, the entire ng-repeat is redrawn.
Changes
Binding to $ scope, add an array to map state values ββto ids.
$scope._users = {"123":{"name":"test","status":"0"}, "124":{"name":"test2", "status":"0"},"125":{"name":"test2", "status":"0"}};
$scope._userStatus = [];
Modify your template to find this array:
Status: <span class="user-status{{user.status}}">{{_userStatus[id]}}</span>
Update the changeStatus function to be the only place where the status text is updated, then do the initial iteration at the beginning.
$scope.changeUserStatus = function(uId, status) {
console.log("Button Clicked.");
$scope._userStatus[uId] = $scope.getStatusInText(status);
}
angular.forEach($scope._users, function(user, uId) {
$scope._userStatus[uId] = $scope.getStatusInText(user.status);
});
source to share