From cdc7db3f35368a9175ed96c63f4bf56593fe1876 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 30 Jul 2014 22:48:37 +0100 Subject: [PATCH] fix(select): do not update selected property of an option element on digest with no change event The `render()` method was being invoked on every turn of the digest cycle, which was inadvertently updating the DOM even when a `change` event had not been triggered. This change only calls the `render()` method when `ctrl.$render()` is called, as part of the NgModelController` lifecycle and when the `modelValue` has significantly changed. Closes #8221 Closes #7715 --- src/ng/directive/select.js | 39 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index 03c65992..c21eeb0c 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -407,13 +407,35 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) { } } ctrl.$setViewValue(value); + render(); }); }); ctrl.$render = render; - // TODO(vojta): can't we optimize this ? - scope.$watch(render); + scope.$watchCollection(valuesFn, render); + if ( multiple ) { + scope.$watchCollection(getSelectedSet, render); + } + + function getSelectedSet() { + var selectedSet = false; + if (multiple) { + var modelValue = ctrl.$modelValue; + if (trackFn && isArray(modelValue)) { + selectedSet = new HashMap([]); + var locals = {}; + for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) { + locals[valueName] = modelValue[trackIndex]; + selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]); + } + } else { + selectedSet = new HashMap(modelValue); + } + } + return selectedSet; + } + function render() { // Temporary location for the option groups before we render them @@ -431,22 +453,11 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) { groupIndex, index, locals = {}, selected, - selectedSet = false, // nothing is selected yet + selectedSet = getSelectedSet(), lastElement, element, label; - if (multiple) { - if (trackFn && isArray(modelValue)) { - selectedSet = new HashMap([]); - for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) { - locals[valueName] = modelValue[trackIndex]; - selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]); - } - } else { - selectedSet = new HashMap(modelValue); - } - } // We now build up the list of options we need (we merge later) for (index = 0; length = keys.length, index < length; index++) {