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
This commit is contained in:
Igor Minar 2013-07-24 16:42:52 -07:00
parent e03402433d
commit d87fa00423
3 changed files with 32 additions and 46 deletions

View file

@ -1220,6 +1220,11 @@ function $CompileProvider($provide) {
if (!interpolateFn) return;
if (name === "multiple" && nodeName_(node) === "SELECT") {
throw new $compileMinErr("selmulti", "Binding to the multiple attribute is not supported. Element: {0}",
startingTag(node));
}
directives.push({
priority: 100,
compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {

View file

@ -199,42 +199,6 @@
*/
/**
* @ngdoc directive
* @name ng.directive:ngMultiple
* @restrict A
*
* @description
* The HTML specs do not require browsers to preserve the special attributes such as multiple.
* (The presence of them means true and absence means false)
* This prevents the angular compiler from correctly retrieving the binding expression.
* To solve this problem, we introduce the `ngMultiple` directive.
*
* @example
<doc:example>
<doc:source>
Check me check multiple: <input type="checkbox" ng-model="checked"><br/>
<select id="select" ng-multiple="checked">
<option>Misko</option>
<option>Igor</option>
<option>Vojta</option>
<option>Di</option>
</select>
</doc:source>
<doc:scenario>
it('should toggle multiple', function() {
expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy();
input('checked').check();
expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy();
});
</doc:scenario>
</doc:example>
*
* @element SELECT
* @param {expression} ngMultiple Angular expression that will be evaluated.
*/
/**
* @ngdoc directive
* @name ng.directive:ngReadonly
@ -334,6 +298,9 @@ var ngAttributeAliasDirectives = {};
// boolean attrs are evaluated
forEach(BOOLEAN_ATTR, function(propName, attrName) {
// binding to multiple is not supported
if (propName == "multiple") return;
var normalized = directiveNormalize('ng-' + attrName);
ngAttributeAliasDirectives[normalized] = function() {
return {

View file

@ -65,16 +65,6 @@ describe('boolean attr directives', function() {
}));
it('should bind multiple', inject(function($rootScope, $compile) {
element = $compile('<select ng-multiple="isMultiple"></select>')($rootScope)
$rootScope.isMultiple=false;
$rootScope.$digest();
expect(element.attr('multiple')).toBeFalsy();
$rootScope.isMultiple='multiple';
$rootScope.$digest();
expect(element.attr('multiple')).toBeTruthy();
}));
it('should bind open', inject(function($rootScope, $compile) {
element = $compile('<details ng-open="isOpen"></details>')($rootScope)
$rootScope.isOpen=false;
@ -84,6 +74,30 @@ describe('boolean attr directives', function() {
$rootScope.$digest();
expect(element.attr('open')).toBeTruthy();
}));
describe('multiple', function() {
it('should NOT bind to multiple via ngMultiple', inject(function($rootScope, $compile) {
element = $compile('<select ng-multiple="isMultiple"></select>')($rootScope)
$rootScope.isMultiple=false;
$rootScope.$digest();
expect(element.attr('multiple')).toBeFalsy();
$rootScope.isMultiple='multiple';
$rootScope.$digest();
expect(element.attr('multiple')).toBeFalsy(); // ignore
}));
it('should throw an exception if binding to multiple attribute', inject(function($rootScope, $compile) {
if (msie < 9) return; //IE8 doesn't support biding to boolean attributes
expect(function() {
$compile('<select multiple="{{isMultiple}}"></select>')
}).toThrow('[$compile:selmulti] Binding to the multiple attribute is not supported. ' +
'Element: <select multiple="{{isMultiple}}">');
}));
});
});