简体   繁体   中英

How to sync my template and typescript code in angular reactive forms, having form groups?cannot find control error

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM