This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
select multi: $render is called twice when model reference changes #12731
Open
Description
This is a followup on a previous issue. I've just found this issue on my own directives and I think it'd be better fixed in angular as well.
The $render
function of a multi-select element is called twice whenever the model value changes by reference.
See plnker: http://plnkr.co/edit/1npwJi5tCS7gGLafYfRp?p=preview
After a model changes, $render is called first from ngModel.
It will be be called again from the viewValue watch of the select directive.
This can be fixed by keeping the last rendered value instead of the last view value in select:
// https://github.com/angular/angular.js/blob/master/src/ng/directive/select.js#L368
var lastRendered;
ngModelCtrl.$render = function() {
selectCtrl.writeValue(ngModelCtrl.$viewValue);
if (attr.multiple) {
lastRendered = shallowCopy(ngModelCtrl.$viewValue);
}
};
...
if (attr.multiple) {
...
// we have to do it on each watch since ngModel watches reference, but
// we need to work of an array, so we need to see if anything was inserted/removed
var lastViewRef = NaN;
scope.$watch(function selectMultipleWatch() {
if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastRendered, ngModelCtrl.$viewValue)) {
ngModelCtrl.$render();
}
lastViewRef = ngModelCtrl.$viewValue;
});
}
To make the spec cover this case. Just add an additional $digest after every $apply (before checking the number of $render calls).