diff --git a/packages/forms/src/validators.ts b/packages/forms/src/validators.ts index 63a962b051..b4ee7d1ec3 100644 --- a/packages/forms/src/validators.ts +++ b/packages/forms/src/validators.ts @@ -125,6 +125,9 @@ export class Validators { * Validator that performs email validation. */ static email(control: AbstractControl): ValidationErrors|null { + if (isEmptyInputValue(control.value)) { + return null; // don't validate empty values to allow optional controls + } return EMAIL_REGEXP.test(control.value) ? null : {'email': true}; } diff --git a/packages/forms/test/template_integration_spec.ts b/packages/forms/test/template_integration_spec.ts index 7426b74fda..783045f6f6 100644 --- a/packages/forms/test/template_integration_spec.ts +++ b/packages/forms/test/template_integration_spec.ts @@ -1265,6 +1265,13 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat tick(); expect(input.nativeElement.value).toEqual(''); + expect(control.hasError('email')).toBe(false); + + input.nativeElement.value = '@'; + dispatchEvent(input.nativeElement, 'input'); + tick(); + + expect(input.nativeElement.value).toEqual('@'); expect(control.hasError('email')).toBe(true); input.nativeElement.value = 'test@gmail.com'; diff --git a/packages/forms/test/validators_spec.ts b/packages/forms/test/validators_spec.ts index dc750534ef..6102542c84 100644 --- a/packages/forms/test/validators_spec.ts +++ b/packages/forms/test/validators_spec.ts @@ -159,6 +159,12 @@ import {map} from 'rxjs/operator/map'; }); describe('email', () => { + it('should not error on an empty string', + () => expect(Validators.email(new FormControl(''))).toBeNull()); + + it('should not error on null', + () => expect(Validators.email(new FormControl(null))).toBeNull()); + it('should error on invalid email', () => expect(Validators.email(new FormControl('some text'))).toEqual({'email': true}));