Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit d87fa00

Browse files
committed
fix(select): don't support binding to select[multiple]
changing the type of select box from single to multiple or the other way around at runtime is currently not supported and the two-way binding does odd stuff when such situation happens. we might eventually support this, but for now we are just going to not allow binding to select[multiple] to prevent people from relying on something that doesn't work. BREAKING CHANGE: binding to select[multiple] directly or via ngMultiple (ng-multiple) directive is not supported. This feature never worked with two-way data-binding, so it's not expected that anybody actually depends on it. Closes #3230
1 parent e034024 commit d87fa00

File tree

3 files changed

+32
-46
lines changed

3 files changed

+32
-46
lines changed

src/ng/compile.js

+5
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,11 @@ function $CompileProvider($provide) {
12201220
if (!interpolateFn) return;
12211221

12221222

1223+
if (name === "multiple" && nodeName_(node) === "SELECT") {
1224+
throw new $compileMinErr("selmulti", "Binding to the multiple attribute is not supported. Element: {0}",
1225+
startingTag(node));
1226+
}
1227+
12231228
directives.push({
12241229
priority: 100,
12251230
compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {

src/ng/directive/booleanAttrs.js

+3-36
Original file line numberDiff line numberDiff line change
@@ -199,42 +199,6 @@
199199
*/
200200

201201

202-
/**
203-
* @ngdoc directive
204-
* @name ng.directive:ngMultiple
205-
* @restrict A
206-
*
207-
* @description
208-
* The HTML specs do not require browsers to preserve the special attributes such as multiple.
209-
* (The presence of them means true and absence means false)
210-
* This prevents the angular compiler from correctly retrieving the binding expression.
211-
* To solve this problem, we introduce the `ngMultiple` directive.
212-
*
213-
* @example
214-
<doc:example>
215-
<doc:source>
216-
Check me check multiple: <input type="checkbox" ng-model="checked"><br/>
217-
<select id="select" ng-multiple="checked">
218-
<option>Misko</option>
219-
<option>Igor</option>
220-
<option>Vojta</option>
221-
<option>Di</option>
222-
</select>
223-
</doc:source>
224-
<doc:scenario>
225-
it('should toggle multiple', function() {
226-
expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();
227-
input('checked').check();
228-
expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();
229-
});
230-
</doc:scenario>
231-
</doc:example>
232-
*
233-
* @element SELECT
234-
* @param {expression} ngMultiple Angular expression that will be evaluated.
235-
*/
236-
237-
238202
/**
239203
* @ngdoc directive
240204
* @name ng.directive:ngReadonly
@@ -334,6 +298,9 @@ var ngAttributeAliasDirectives = {};
334298

335299
// boolean attrs are evaluated
336300
forEach(BOOLEAN_ATTR, function(propName, attrName) {
301+
// binding to multiple is not supported
302+
if (propName == "multiple") return;
303+
337304
var normalized = directiveNormalize('ng-' + attrName);
338305
ngAttributeAliasDirectives[normalized] = function() {
339306
return {

test/ng/directive/booleanAttrsSpec.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,6 @@ describe('boolean attr directives', function() {
6565
}));
6666

6767

68-
it('should bind multiple', inject(function($rootScope, $compile) {
69-
element = $compile('<select ng-multiple="isMultiple"></select>')($rootScope)
70-
$rootScope.isMultiple=false;
71-
$rootScope.$digest();
72-
expect(element.attr('multiple')).toBeFalsy();
73-
$rootScope.isMultiple='multiple';
74-
$rootScope.$digest();
75-
expect(element.attr('multiple')).toBeTruthy();
76-
}));
77-
7868
it('should bind open', inject(function($rootScope, $compile) {
7969
element = $compile('<details ng-open="isOpen"></details>')($rootScope)
8070
$rootScope.isOpen=false;
@@ -84,6 +74,30 @@ describe('boolean attr directives', function() {
8474
$rootScope.$digest();
8575
expect(element.attr('open')).toBeTruthy();
8676
}));
77+
78+
79+
describe('multiple', function() {
80+
it('should NOT bind to multiple via ngMultiple', inject(function($rootScope, $compile) {
81+
element = $compile('<select ng-multiple="isMultiple"></select>')($rootScope)
82+
$rootScope.isMultiple=false;
83+
$rootScope.$digest();
84+
expect(element.attr('multiple')).toBeFalsy();
85+
$rootScope.isMultiple='multiple';
86+
$rootScope.$digest();
87+
expect(element.attr('multiple')).toBeFalsy(); // ignore
88+
}));
89+
90+
91+
it('should throw an exception if binding to multiple attribute', inject(function($rootScope, $compile) {
92+
if (msie < 9) return; //IE8 doesn't support biding to boolean attributes
93+
94+
expect(function() {
95+
$compile('<select multiple="{{isMultiple}}"></select>')
96+
}).toThrow('[$compile:selmulti] Binding to the multiple attribute is not supported. ' +
97+
'Element: <select multiple="{{isMultiple}}">');
98+
99+
}));
100+
});
87101
});
88102

89103

0 commit comments

Comments
 (0)