Skip to content

Commit 2575b57

Browse files
committed
fix(required): false is a valid model value when not a checkbox
Make the `required` directive accept the model value `false` when it is not an <input> element or when the <input> element is not a checkbox Closes angular#3490 angular#2594
1 parent d307242 commit 2575b57

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

src/ng/directive/input.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1228,14 +1228,15 @@ var requiredDirective = function() {
12281228
attr.required = true; // force truthy in case we are on non input element
12291229

12301230
var validator = function(value) {
1231-
if (attr.required && (isEmpty(value) || value === false)) {
1231+
if (attr.required && (isEmpty(value) || !acceptFalse && value === false)) {
12321232
ctrl.$setValidity('required', false);
12331233
return;
12341234
} else {
12351235
ctrl.$setValidity('required', true);
12361236
return value;
12371237
}
1238-
};
1238+
},
1239+
acceptFalse = nodeName_(elm).toLowerCase() !== 'input' || attr.type !== 'checkbox';
12391240

12401241
ctrl.$formatters.push(validator);
12411242
ctrl.$parsers.unshift(validator);

test/ng/directive/inputSpec.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,25 @@ describe('input', function() {
10931093
compileInput('<input type="text" ng-model="notDefiend" required />');
10941094
scope.$digest();
10951095
expect(inputElm).toBeInvalid();
1096-
})
1096+
});
1097+
1098+
it('should allow `false` as a valid value when the input type is not "checkbox"', function() {
1099+
compileInput('<input type="radio" ng-value="true" ng-model="answer" required />' +
1100+
'<input type="radio" ng-value="false" ng-model="answer" required />');
1101+
1102+
scope.$apply();
1103+
expect(inputElm).toBeInvalid();
1104+
1105+
scope.$apply(function() {
1106+
scope.answer = true;
1107+
});
1108+
expect(inputElm).toBeValid();
1109+
1110+
scope.$apply(function() {
1111+
scope.answer = false;
1112+
});
1113+
expect(inputElm).toBeValid();
1114+
});
10971115
});
10981116

10991117

test/ng/directive/selectSpec.js

+24
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,30 @@ describe('select', function() {
11981198
});
11991199
expect(element).toBeValid();
12001200
});
1201+
1202+
it('should allow falsy values as values', function() {
1203+
createSelect({
1204+
'ng-model': 'value',
1205+
'ng-options': 'item.value as item.name for item in values',
1206+
'ng-required': 'required'
1207+
}, true);
1208+
1209+
scope.$apply(function() {
1210+
scope.values = [{name: 'True', value: true}, {name: 'False', value: false}];
1211+
scope.required = false;
1212+
});
1213+
1214+
element.val('1');
1215+
browserTrigger(element, 'change');
1216+
expect(element).toBeValid();
1217+
expect(scope.value).toBe(false);
1218+
1219+
scope.$apply(function() {
1220+
scope.required = true;
1221+
});
1222+
expect(element).toBeValid();
1223+
expect(scope.value).toBe(false);
1224+
});
12011225
});
12021226
});
12031227

0 commit comments

Comments
 (0)