Problem
I have a combo box, basically a select
element that is filled with an array of complex objects by ng-options
. When I update any object of the collection on second-level, this change is not applied to the combo box.
This is also documented on the AngularJS web site:
Note that
$watchCollection
does a shallow comparison of the properties of the object (or the items in the collection if the model is an array). This means that changing a property deeper than the first level inside the object/collection will not trigger a re-rendering.
Angular view
<div ng-app="testApp">
<div ng-controller="Ctrl">
<select ng-model="selectedOption"
ng-options="(selectedOption.id + ' - ' + selectedOption.name) for selectedOption in myCollection track by selectedOption.id">
</select>
<button ng-click="changeFirstLevel()">Change first level</button>
<button ng-click="changeSecondLevel()">Change second level</button>
<p>Collection: {{ myCollection }}</p>
<p>Selected: {{ selectedOption }}</p>
</div>
</div>
Angular controller
var testApp = angular.module('testApp', []);
testApp.controller('Ctrl', ['$scope', function ($scope) {
$scope.myCollection = [
{
id: '1',
name: 'name1',
nested: {
value: 'nested1'
}
}
];
$scope.changeFirstLevel = function() {
var newElem = {
id: '1',
name: 'newName1',
nested: {
value: 'newNested1'
}
};
$scope.myCollection[0] = newElem;
};
$scope.changeSecondLevel = function() {
var newElem = {
id: '1',
name: 'name1',
nested: {
value: 'newNested1'
}
};
$scope.myCollection[0] = newElem;
};
}]);
You can also run it live in this JSFiddle.
Question
I do understand that AngularJS does not watch complex objects within ng-options
for performance reasons. But is there any workaround for this, i.e. can I manually trigger re-rendering? Some posts mention $timeout
or $scope.apply
as a solution, but I could utilize neither.
changeSecondLevel()
performs a HTTP request that returns an entire set of new elements that I reassign tomyCollection
. I just chose a single element here for the sake of simplicity. – Loisid
value unique inmyCollection
? And when you say you reassignmyCollection
, do you domyCollection = ...
or do you iterate through the list as in your example and domyCollection[i] = ...
? – Cornuted