From 752365e87c70d493c7db9a6aa0f21d24b42ae0f2 Mon Sep 17 00:00:00 2001 From: Jeff Balboni Date: Sun, 26 Jan 2014 16:17:36 -0500 Subject: [PATCH] fix(select): avoid checking option element selected properties in render In Firefox, hovering over an option in an open select menu updates the selected property of option elements. This means that when a render is triggered by the digest cycle, and the list of options is being rendered, the selected properties are reset to the values from the model and the option hovered over changes. This fix changes the code to only use DOM elements' selected properties in a comparison when a change event has been fired. Otherwise, the internal new and existing option arrays are used. Closes #2448 Closes #5994 --- src/ng/directive/select.js | 8 +++++++- test/ng/directive/selectSpec.js | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index 0b562cca686c..628d21776b85 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -394,6 +394,12 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) { value = valueFn(scope, locals); } } + // Update the null option's selected property here so $render cleans it up correctly + if (optionGroupsCache[0].length > 1) { + if (optionGroupsCache[0][1].id !== key) { + optionGroupsCache[0][1].selected = false; + } + } } ctrl.$setViewValue(value); }); @@ -531,7 +537,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) { lastElement.val(existingOption.id = option.id); } // lastElement.prop('selected') provided by jQuery has side-effects - if (lastElement[0].selected !== option.selected) { + if (existingOption.selected !== option.selected) { lastElement.prop('selected', (existingOption.selected = option.selected)); } } else { diff --git a/test/ng/directive/selectSpec.js b/test/ng/directive/selectSpec.js index 6fcd1fe05f82..d270f438704f 100644 --- a/test/ng/directive/selectSpec.js +++ b/test/ng/directive/selectSpec.js @@ -733,6 +733,27 @@ describe('select', function() { expect(sortedHtml(options[2])).toEqual(''); }); + it('should not update selected property of an option element on digest with no change event', + function() { + createSingleSelect(); + + scope.$apply(function() { + scope.values = [{name: 'A'}, {name: 'B'}, {name: 'C'}]; + scope.selected = scope.values[0]; + }); + + var options = element.find('option'); + var optionToSelect = options.eq(1); + + expect(optionToSelect.text()).toBe('B'); + + optionToSelect.prop('selected', true); + scope.$digest(); + + expect(optionToSelect.prop('selected')).toBe(true); + expect(scope.selected).toBe(scope.values[0]); + }); + describe('binding', function() { it('should bind to scope value', function() {