From 85e392f3543ef5285c7e90e843af0ab522cb0531 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 10 Dec 2015 12:16:29 +0100 Subject: [PATCH] fix(ngOptions): don't skip optgroup elements with value === '' Internet Explorer 11 returns '' for optgroup elements without a value attribute. We only want to skip option elements with value '' Fixes #13487 Closes #13489 --- src/ng/directive/ngOptions.js | 2 +- test/ng/directive/ngOptionsSpec.js | 129 +++++++++++++++++++++++++++-- 2 files changed, 123 insertions(+), 8 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 09939af9fbf5..bb29b7cec1c7 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -647,7 +647,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { (current === emptyOption_ || current === unknownOption_ || current.nodeType === NODE_TYPE_COMMENT || - current.value === '')) { + (nodeName_(current) === 'option' && current.value === ''))) { current = current.nextSibling; } } diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index 21c86b55d64c..b234312e906d 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -1,6 +1,6 @@ 'use strict'; -describe('ngOptions', function() { +ddescribe('ngOptions', function() { var scope, formElement, element, $compile, linkLog; @@ -1553,16 +1553,19 @@ describe('ngOptions', function() { expect(element).toEqualSelectValue(scope.selected); - var first = jqLite(element.find('optgroup')[0]); - var b = jqLite(first.find('option')[0]); - var d = jqLite(first.find('option')[1]); + var optgroups = element.find('optgroup'); + expect(optgroups.length).toBe(2); + + var first = optgroups.eq(0); + var b = first.find('option').eq(0); + var d = first.find('option').eq(1); expect(first.attr('label')).toEqual('first'); expect(b.text()).toEqual('B'); expect(d.text()).toEqual('D'); - var second = jqLite(element.find('optgroup')[1]); - var c = jqLite(second.find('option')[0]); - var e = jqLite(second.find('option')[1]); + var second = optgroups.eq(1); + var c = second.find('option').eq(0); + var e = second.find('option').eq(1); expect(second.attr('label')).toEqual('second'); expect(c.text()).toEqual('C'); expect(e.text()).toEqual('E'); @@ -1575,6 +1578,118 @@ describe('ngOptions', function() { }); + it('should group when the options are available on compile time', function() { + scope.values = [{name: 'C', group: 'first'}, + {name: 'D', group: 'second'}, + {name: 'F', group: 'first'}, + {name: 'G', group: 'second'}]; + scope.selected = scope.values[3]; + + createSelect({ + 'ng-model': 'selected', + 'ng-options': 'item as item.name group by item.group for item in values' + }); + + expect(element).toEqualSelectValue(scope.selected); + + var optgroups = element.find('optgroup'); + expect(optgroups.length).toBe(2); + + var first = optgroups.eq(0); + var c = first.find('option').eq(0); + var f = first.find('option').eq(1); + expect(first.attr('label')).toEqual('first'); + expect(c.text()).toEqual('C'); + expect(f.text()).toEqual('F'); + + var second = optgroups.eq(1); + var d = second.find('option').eq(0); + var g = second.find('option').eq(1); + expect(second.attr('label')).toEqual('second'); + expect(d.text()).toEqual('D'); + expect(g.text()).toEqual('G'); + + scope.$apply(function() { + scope.selected = scope.values[0]; + }); + + expect(element).toEqualSelectValue(scope.selected); + }); + + + it('should group when the options are updated', function() { + var optgroups, one, two, three, alpha, beta, gamma, delta, epsilon; + + createSelect({ + 'ng-model': 'selected', + 'ng-options': 'i.name group by i.cls for i in list' + }); + + scope.list = [ + {cls: 'one', name: 'Alpha'}, + {cls: 'one', name: 'Beta'}, + {cls: 'two', name: 'Gamma'} + ]; + scope.$digest(); + + optgroups = element.find('optgroup'); + expect(optgroups.length).toBe(2); + + one = optgroups.eq(0); + expect(one.children('option').length).toBe(2); + + alpha = one.find('option').eq(0); + beta = one.find('option').eq(1); + expect(one.attr('label')).toEqual('one'); + expect(alpha.text()).toEqual('Alpha'); + expect(beta.text()).toEqual('Beta'); + + two = optgroups.eq(1); + expect(two.children('option').length).toBe(1); + + gamma = two.find('option').eq(0); + expect(two.attr('label')).toEqual('two'); + expect(gamma.text()).toEqual('Gamma'); + + // Remove item from first group, add item to second group, add new group + scope.list.shift(); + scope.list.push( + {cls: 'two', name: 'Delta'}, + {cls: 'three', name: 'Epsilon'} + ); + scope.$digest(); + + optgroups = element.find('optgroup'); + expect(optgroups.length).toBe(3); + + // Group with removed item + one = optgroups.eq(0); + expect(one.children('option').length).toBe(1); + + beta = one.find('option').eq(0); + expect(one.attr('label')).toEqual('one'); + expect(beta.text()).toEqual('Beta'); + + // Group with new item + two = optgroups.eq(1); + expect(two.children('option').length).toBe(2); + + gamma = two.find('option').eq(0); + expect(two.attr('label')).toEqual('two'); + expect(gamma.text()).toEqual('Gamma'); + delta = two.find('option').eq(1); + expect(two.attr('label')).toEqual('two'); + expect(delta.text()).toEqual('Delta'); + + // New group + three = optgroups.eq(2); + expect(three.children('option').length).toBe(1); + + epsilon = three.find('option').eq(0); + expect(three.attr('label')).toEqual('three'); + expect(epsilon.text()).toEqual('Epsilon'); + }); + it('should place non-grouped items in the list where they appear', function() { createSelect({ 'ng-model': 'selected',