describe('match', () => {
let form: FormGroup;
+ let x: FormControl;
+ let y: FormControl;
beforeEach(() => {
+ x = new FormControl('aaa');
+ y = new FormControl('aaa');
form = new FormGroup({
- x: new FormControl(),
- y: new FormControl()
+ x: x,
+ y: y
});
});
it('should error when values are different', () => {
- const x = form.get('x');
- const y = form.get('y');
- x.setValue('aaa');
y.setValue('aab');
CdValidators.match('x', 'y')(form);
expect(x.hasError('match')).toBeFalsy();
});
it('should not error when values are equal', () => {
- const x = form.get('x');
- const y = form.get('y');
- x.setValue('aaa');
- y.setValue('aaa');
CdValidators.match('x', 'y')(form);
expect(x.hasError('match')).toBeFalsy();
expect(y.hasError('match')).toBeFalsy();
});
+
+ it('should unset error when values are equal', () => {
+ y.setErrors({ match: true });
+ CdValidators.match('x', 'y')(form);
+ expect(x.hasError('match')).toBeFalsy();
+ expect(y.hasError('match')).toBeFalsy();
+ expect(y.valid).toBeTruthy();
+ });
+
+ it('should keep other existing errors', () => {
+ y.setErrors({ match: true, notUnique: true });
+ CdValidators.match('x', 'y')(form);
+ expect(x.hasError('match')).toBeFalsy();
+ expect(y.hasError('match')).toBeFalsy();
+ expect(y.hasError('notUnique')).toBeTruthy();
+ expect(y.valid).toBeFalsy();
+ });
});
describe('unique', () => {
}
/**
- * Validate if control1 and control2 have the same value.
- * Error will be added to control2.
- *
- * @param {string} control1
- * @param {string} control2
+ * Validator that requires that both specified controls have the same value.
+ * Error will be added to the `path2` control.
+ * @param {string} path1 A dot-delimited string that define the path to the control.
+ * @param {string} path2 A dot-delimited string that define the path to the control.
+ * @return {ValidatorFn} Returns a validator function that always returns `null`.
+ * If the validation fails an error map with the `match` property will be set
+ * on the `path2` control.
*/
- static match(control1: string, control2: string): ValidatorFn {
+ static match(path1: string, path2: string): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
- if (control.get(control1).value !== control.get(control2).value) {
- control.get(control2).setErrors({ ['match']: true });
+ const ctrl1 = control.get(path1);
+ const ctrl2 = control.get(path2);
+ if (ctrl1.value !== ctrl2.value) {
+ ctrl2.setErrors({ match: true });
+ } else {
+ const hasError = ctrl2.hasError('match');
+ if (hasError) {
+ // Remove the 'match' error. If no more errors exists, then set
+ // the error value to 'null', otherwise the field is still marked
+ // as invalid.
+ const errors = ctrl2.errors;
+ _.unset(errors, 'match');
+ ctrl2.setErrors(_.isEmpty(_.keys(errors)) ? null : errors);
+ }
}
return null;
};