Reputation: 123
I have such custom validator:
static isEmail(control:Control):{[key:string]:boolean} {
let emailRegExp = new RegExp("^[-a-z0-9~!$%^&*_=+}{'?]+(.[-a-z0-9~!$%^&*_=+}{'?]+)*@([a-z0-9_][-a-z0-9_]*(.[-a-z0-9_]+)*.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))(:[0-9]{1,5})?$", 'i');
if (control.value.match(emailRegExp)) {
return {isEmail: true};
}
return {isEmail: false};
}
Use it in component:
loginForm:ControlGroup;
constructor(private _router:Router,
private _loginService:LoginService,
private _formBuilder:FormBuilder) {
this.loginForm = _formBuilder.group({
email: ['', Validators.compose([
Validators.required,
Validators.minLength(8),
FormValidationService.isEmail
])],
password: ['', Validators.compose([
Validators.required,
Validators.minLength(8),
Validators.maxLength(30),
FormValidationService.isPassword
])]
});
}
And template:
<form id="login-form" role="form" [ngFormModel]="loginForm" (ngSubmit)="onLoginSubmit()">
<div class="form-group">
<label class="control-label" for="loginFormEmail">Email</label>
<input type="text" id="loginFormEmail" class="form-control"
ngControl="email" #email="ngForm">
<div *ngIf="email.dirty && !email.valid">
<div class="alert alert-danger" role="alert" [hidden]="!email.errors.minlength">
Email field must have more then 8 characters
</div>
<div class="alert alert-danger" role="alert" [hidden]="email.errors.isEmail">
Email not valid
</div>
</div>
</div>
<div class="form-group">
<label class="control-label" for="loginFormPassword">Password</label>
<input type="password" id="loginFormPassword" class="form-control"
ngControl="password" #password="ngForm">
<div *ngIf="password.dirty && !password.valid">
<div class="alert alert-danger" role="alert" [hidden]="!password.errors.minlength">
Password field must have more then 8 characters
</div>
<div class="alert alert-danger" role="alert" [hidden]="!password.errors.maxlength">
Password field must have no more then 30 characters
</div>
<div class="alert alert-danger" role="alert" [hidden]="password.errors.isPassword">
Password must meet the following rules:
<ul>
<li>At least one upper case english letter</li>
<li>At least one lower case english letter</li>
<li>At least one digit</li>
<li>At least one special character</li>
</ul>
</div>
</div>
</div>
<p>If you forgot your password you can <a (click)="toForgot()">reset it</a>.</p>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block" [disabled]="!loginForm.valid">Login</button>
</div>
</form>
If you look in screenshot you can see that custom validator return my value. But regardless of its value control.valid always false, so form invalid to.
I try to set control.valid = true
, but this field have only getter.
Upvotes: 1
Views: 2492
Reputation: 123
I found answer. When control value is valid you must return null in your custom validator:
static isPassword(control:Control):{[key:string]:boolean} {
let passwordRegExp = new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
if (control.value.match(passwordRegExp)) {
return null;
}
return {isPassword: false};
}
Upvotes: 1
Reputation: 202306
You mixed inline form definition with ngForm and definition in JS code using the FormBuilder class.
You should refactor your input definitions this way to use the ngFormControl directive:
<input [ngFomControl]="loginForm.controls.password" .../>
Upvotes: 0
Reputation: 658027
I think you need to add ngControlGroup
to wrapping elements otherwise the form won't track the containing input elements
<div class="form-group" ngControlGroup="someName">
See also NgControlGroup
Upvotes: 0