Skip to content

Commit 1c462c7

Browse files
committed
fix(ngModel): let aliased validator directives work on any element
`ng-(pattern|minlength|maxlength)` directives will now validate the `ngModel` when on an element that is not an `input` or a `textarea`. Previously, only their HTML5 counterparts worked on every element. The commit also adds a test for `ng-required`, although that validator worked on all elements before this fix. Fixes angular#12158
1 parent f95bc42 commit 1c462c7

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

src/jqLite.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,8 @@ function getBooleanAttrName(element, name) {
556556
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
557557
}
558558

559-
function getAliasedAttrName(element, name) {
560-
var nodeName = element.nodeName;
561-
return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
559+
function getAliasedAttrName(name) {
560+
return ALIASED_ATTR[name];
562561
}
563562

564563
forEach({

src/ng/compile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
10771077

10781078
var node = this.$$element[0],
10791079
booleanKey = getBooleanAttrName(node, key),
1080-
aliasedKey = getAliasedAttrName(node, key),
1080+
aliasedKey = getAliasedAttrName(key),
10811081
observer = key,
10821082
nodeName;
10831083

test/ng/directive/validatorsSpec.js

+73
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,24 @@ describe('validators', function() {
204204
expect($rootScope.form.test.$error.pattern).toBe(true);
205205
expect(inputElm).not.toBeValid();
206206
});
207+
208+
209+
it('should validate on non-input elements', inject(function($compile) {
210+
$rootScope.pattern = '\\d{4}';
211+
var elm = $compile('<span ng-model="value" pattern="\\d{4}"></span>')($rootScope);
212+
var elmNg = $compile('<span ng-model="value" ng-pattern="pattern"></span>')($rootScope);
213+
var ctrl = elm.controller('ngModel');
214+
var ctrlNg = elmNg.controller('ngModel');
215+
216+
expect(ctrl.$error.pattern).not.toBe(true);
217+
expect(ctrlNg.$error.pattern).not.toBe(true);
218+
219+
ctrl.$setViewValue('12');
220+
ctrlNg.$setViewValue('12');
221+
222+
expect(ctrl.$error.pattern).toBe(true);
223+
expect(ctrlNg.$error.pattern).toBe(true);
224+
}));
207225
});
208226

209227

@@ -268,6 +286,24 @@ describe('validators', function() {
268286
helper.changeInputValueTo('12345');
269287
expect(ctrl.$isEmpty).toHaveBeenCalledWith('12345');
270288
});
289+
290+
291+
it('should validate on non-input elements', inject(function($compile) {
292+
$rootScope.min = 3;
293+
var elm = $compile('<span ng-model="value" minlength="{{min}}"></span>')($rootScope);
294+
var elmNg = $compile('<span ng-model="value" ng-minlength="min"></span>')($rootScope);
295+
var ctrl = elm.controller('ngModel');
296+
var ctrlNg = elmNg.controller('ngModel');
297+
298+
expect(ctrl.$error.minlength).not.toBe(true);
299+
expect(ctrlNg.$error.minlength).not.toBe(true);
300+
301+
ctrl.$setViewValue('12');
302+
ctrlNg.$setViewValue('12');
303+
304+
expect(ctrl.$error.minlength).toBe(true);
305+
expect(ctrlNg.$error.minlength).toBe(true);
306+
}));
271307
});
272308

273309

@@ -438,6 +474,24 @@ describe('validators', function() {
438474
helper.changeInputValueTo('12345');
439475
expect(ctrl.$isEmpty).toHaveBeenCalledWith('12345');
440476
});
477+
478+
479+
it('should validate on non-input elements', inject(function($compile) {
480+
$rootScope.max = 3;
481+
var elm = $compile('<span ng-model="value" maxlength="{{max}}"></span>')($rootScope);
482+
var elmNg = $compile('<span ng-model="value" ng-maxlength="max"></span>')($rootScope);
483+
var ctrl = elm.controller('ngModel');
484+
var ctrlNg = elmNg.controller('ngModel');
485+
486+
expect(ctrl.$error.maxlength).not.toBe(true);
487+
expect(ctrlNg.$error.maxlength).not.toBe(true);
488+
489+
ctrl.$setViewValue('1234');
490+
ctrlNg.$setViewValue('1234');
491+
492+
expect(ctrl.$error.maxlength).toBe(true);
493+
expect(ctrlNg.$error.maxlength).toBe(true);
494+
}));
441495
});
442496

443497

@@ -532,6 +586,7 @@ describe('validators', function() {
532586
expect(inputElm).toBeValid();
533587
});
534588

589+
535590
it('should validate emptiness against the viewValue', function() {
536591
var inputElm = helper.compileInput('<input type="text" name="input" ng-model="value" required />');
537592

@@ -545,5 +600,23 @@ describe('validators', function() {
545600
helper.changeInputValueTo('12345');
546601
expect(ctrl.$isEmpty).toHaveBeenCalledWith('12345');
547602
});
603+
604+
605+
it('should validate on non-input elements', inject(function($compile) {
606+
$rootScope.value = '12';
607+
var elm = $compile('<span ng-model="value" required></span>')($rootScope);
608+
var elmNg = $compile('<span ng-model="value" ng-required="true"></span>')($rootScope);
609+
var ctrl = elm.controller('ngModel');
610+
var ctrlNg = elmNg.controller('ngModel');
611+
612+
expect(ctrl.$error.required).not.toBe(true);
613+
expect(ctrlNg.$error.required).not.toBe(true);
614+
615+
ctrl.$setViewValue('');
616+
ctrlNg.$setViewValue('');
617+
618+
expect(ctrl.$error.required).toBe(true);
619+
expect(ctrlNg.$error.required).toBe(true);
620+
}));
548621
});
549622
});

0 commit comments

Comments
 (0)