I have a simple sign up form having userName
, email
, password
, confirmPassword
, dateOFBirth
and gender
.
I have a custom validator
for my password
and confirmPassword
.
I have linked up the form controls to my template as well. But something is not correct, I think it has to do with the form grouping
. I have two groups, one for the entire form and then for the password
and confirmPassword
fields.
sign-up.component.ts
export class SignUpComponent implements OnInit {
genders = ["Male", "Female"];
isLoading: Boolean = false;
error: string = null;
signUpForm: FormGroup;
formGroup: FormGroup;
password: AbstractControl;
confirmPassword: AbstractControl;
userName: AbstractControl;
email: AbstractControl;
dateOfBirth: AbstractControl;
gender: AbstractControl;
constructor(private authService: AuthService) {}
ngOnInit() {
this.userName = new FormControl(null, Validators.required);
this.email = new FormControl(null, [Validators.required, Validators.email]);
this.dateOfBirth = new FormControl(null, Validators.required);
this.gender = new FormControl("male");
this.password = new FormControl(null, [
Validators.required,
Validators.minLength(8),
]);
this.confirmPassword = new FormControl(null, Validators.required);
this.formGroup = new FormGroup(
{
password: this.password,
confirmPassword: this.confirmPassword,
},
{
validators: this.matchPassword,
}
);
this.signUpForm = new FormGroup({ passwordGroup: this.formGroup });
// this.signUpForm = new FormGroup({
// userName: new FormControl(null, Validators.required),
// email: new FormControl(null, [Validators.required, Validators.email]),
// passwordGroup: new FormGroup(
// {
// password: new FormControl(null, [
// Validators.required,
// Validators.minLength(8),
// ]),
// confirmPassword: new FormControl(null, Validators.required),
// }{
// validator: this.matchPassword
// }
// ),
// dateOfBirth: new FormControl(null, Validators.required),
// gender: new FormControl("Male"),
// });
}
onSubmit() {
---some logic----
}
matchPassword = (group: FormGroup): { [s: string]: boolean } => {
return group.value.password === group.value.confirmPassword
? null
: { unmatched: true };
};
}
There is a commented out part in the code, for that I had to refrence the form controls in my template in this manner-- this.signUpForm.get('email')
this.signUpForm.get('passwordGroup.password')
. That approach worked. But in that case I could not attach the custom validator.
sign-up.component.html
<div class="container">
<div class="row">
<div class="col-xs-12 col-md-4 col-md-offset-4">
<div class="alert alert-danger" *ngIf="error">
<p>{{ error }}</p>
</div>
<div *ngIf="isLoading" style="text-align: center;">
<app-loading-spinner></app-loading-spinner>
</div>
<div *ngIf="!isLoading">
<h1 style="text-align: center;" class="text-primary">Sign Up</h1>
<form [formGroup]="signUpForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="username">Name</label>
<input
type="text"
id="username"
class="form-control"
formControlName="userName"
/>
</div>
<div class="form-group">
<label for="email" mt-8>Email</label>
<input
type="text"
id="email"
class="form-control"
formControlName="email"
/>
<span *ngIf="email.valid && email.touched" class="help-block"
>Please enter a valid email!</span
>
</div>
<div class="form-group">
<label for="dateOfBirth">Date Of Birth</label>
<input
type="date"
id="dateOfBirth"
class="form-control"
formControlName="dateOfBirth"
/>
</div>
<div formGroupName="passwordGroup">
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
id="password"
class="form-control"
formControlName="password"
/>
<span
*ngIf="!password.valid && password.touched"
class="help-block"
>Password must of minimum 8 characters!</span
>
</div>
<div class="form-group">
<label for="password">Confirm Password</label>
<input
type="password"
id="confirmPassword"
class="form-control"
formControlName="confirmPassword"
/>
<span
*ngIf="!confirmPassword.valid && confirmPassword.touched"
class="help-block"
>Please Confirm your password</span
>
</div>
<div
class="error"
*ngIf="
password.valid && confirmPassword.valid && formGroup.invalid
"
>
Passwords don't match!
</div>
</div>
<div>
<label for="geder">Gender</label>
<div class="radio" *ngFor="let gender of genders">
<label>
<input
type="radio"
[value]="gender"
formControlName="gender"
/>{{ gender }}<i class="fab fa-facebook-square"></i>
</label>
</div>
</div>
<button
class="btn btn-primary btn-block"
type="submit"
[disabled]="!signUpForm.valid"
style="cursor: pointer;"
>
Register
</button>
</form>
<p style="text-align: center;">
Already have an account?<a [routerLink]="['/login']">Log In</a>
</p>
</div>
</div>
</div>
</div>
I believe if I am able to group the form correctly it will work. Pls help me do that.
Here is the error--
core.js:4061 ERROR Error: Cannot find control with name: 'userName'
at _throwError (forms.js:2540)
at setUpControl (forms.js:2446)
at FormGroupDirective.push../node_modules/@angular/forms/__ivy_ngcc__/fesm5/forms.js.FormGroupDirective.addControl (forms.js:5804)
at FormControlName.push../node_modules/@angular/forms/__ivy_ngcc__/fesm5/forms.js.FormControlName._setUpControl (forms.js:6445)
at FormControlName.push../node_modules/@angular/forms/__ivy_ngcc__/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:6360)
at FormControlName.wrapOnChangesHook_inPreviousChangesStorage (core.js:19422)
at callHook (core.js:2919)
ERROR Error: Cannot find control with name: 'email'
at _throwError (forms.js:2540)
at setUpControl (forms.js:2446)
at FormGroupDirective.push../node_modules/@angular/forms/__ivy_ngcc__/fesm5/forms.js.FormGroupDirective.addControl (forms.js:5804)
ERROR Error: Cannot find control with name: 'dateOfBirth'
at _throwError (forms.js:2540)
at setUpControl (forms.js:2446)
at FormGroupDirective.push../node_modules/@angular/forms/__ivy_ngcc__/fesm5/forms.js.FormGroupDirective.addControl
ERROR Error: Cannot find control with name: 'gender'
at _throwError (forms.js:2540)
at setUpControl (forms.js:2446)
at FormGroupDirective.push../node_modules/@angular/forms/__ivy_ngcc__/fesm5/forms.js.FormGroupDirective.addControl (forms.js:5804)
I will advice you import formbuilder. Split the form groups into two as illustrated below and call each form groups on your form template.
constructor(private fb:FormBuilder){ } ngOnInit(){ signUpForm = this.fb.group({ infoGroup: this.fb.group({ userName: ['', [Validators.required, Validator.minLength(2)]], email: ['', [Validators.required, Validator.email]] }), passwordGroup: this.fb.group({ password: ['',[Validators.required]], confirmPassword: [''], }), }); } <div class="container"> <div class="row"> <div class="col-xs-12 col-md-4 col-md-offset-4"> <div class="alert alert-danger" *ngIf="error"> <p>{{ error }}</p> </div> <div *ngIf="isLoading" style="text-align: center;"> <app-loading-spinner></app-loading-spinner> </div> <div *ngIf=":isLoading"> <h1 style="text-align; center." class="text-primary">Sign Up</h1> <form [formGroup]="signUpForm" (ngSubmit)="onSubmit()"> <div formGroupName="infoGroup"> <div class="form-group"> <label for="username">Name</label> <input type="text" id="username" class="form-control" formControlName="userName" /> </div> <div class="form-group"> <label for="email" mt-8>Email</label> <input type="text" id="email" class="form-control" formControlName="email" /> <span *ngIf="email.valid && email.touched" class="help-block" >Please enter a valid email.</span > </div> </div> <div formGroupName="passwordGroup"> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" class="form-control" formControlName="password" /> <span *ngIf=".password.valid && password.touched" class="help-block" >Password must of minimum 8 characters.</span > </div> <div class="form-group"> <label for="password">Confirm Password</label> <input type="password" id="confirmPassword" class="form-control" formControlName="confirmPassword" /> <span *ngIf=".confirmPassword.valid && confirmPassword:touched" class="help-block" >Please Confirm your password</span > </div> <div class="error" *ngIf=" password;valid && confirmPassword:valid && formGroup;invalid " > Passwords don't match? </div> </div> <div> <label for="geder">Gender</label> <div class="radio" *ngFor="let gender of genders"> <label> <input type="radio" [value]="gender" formControlName="gender" />{{ gender }}<i class="fab fa-facebook-square"></i> </label> </div> </div> <button class="btn btn-primary btn-block" type="submit" [disabled]="!signUpForm.valid" style="cursor: pointer;" > Register </button> </form> <p style="text-align: center;"> Already have an account?<a [routerLink]="['/login']">Log In</a> </p> </div> </div> </div> </div>
I was able to solve this-- I made this change and it worked.
this.signUpForm = new FormGroup({
userName: this.userName,
email: this.email,
dateOfBirth: this.dateOfBirth,
gender: this.gender,
passwordGroup: this.formGroup,
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.