无法访问嵌套表单值以验证表单

时间:2017-09-29 14:40:29

标签: angular typescript angular-reactive-forms

我在使用Angular中的Reactive Forms验证嵌套表单时遇到问题。我有一个正常工作的注册表单,但在我添加表单组以分别检查有效性后,我遇到了一些错误。这些错误是因为验证器只在主窗体上工作,而不是嵌套的验证器。我试图访问嵌套表单的值,但我得到的是表单的值未定义。

component.ts

import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms";

@Component({
  selector: 'my-page-sign-up',
  styleUrls: ['./sign-up.component.scss'],
  templateUrl: './sign-up.component.html'
})

export class PageSignUpComponent implements OnInit {

 myForm: FormGroup;

 constructor(private fb: FormBuilder) {
                    this.myForm = this.fb.group({
                      'emailPass': this.fb.group({
                        email: ['', [
                          Validators.required,
                          Validators.email
                        ]],
                        password: ['', Validators.required],
                        confirmPassword: ['', Validators.compose([
                            Validators.required,
                            this.isEqualPassword.bind(this)
                        ])],
                      }),
                      })
                      }

  isEqualPassword(control: FormControl): {[s: string]: boolean} {
    if (!this.myForm.controls) {
        return {passwordsNotMatch: true};

    }
    if (control.value !== this.myForm.controls['password'].value) {
        return {passwordsNotMatch: true};
    }
}
}

HTML

<form [formGroup]="myForm" (ngSubmit)="onSignup()">
<div formGroupName="emailPass" class="form-group">
    <md-input-container class="col-md-6 md-icon-left">
        <md-icon class="material-icons">mail_outline</md-icon>
        <input formControlName="email" mdInput #email type="email" name="email" class="form-control" placeholder="Email">
        <!--md-hint *ngIf="!myForm.get(['emailPass', 'email']).pristine && myForm.hasError('noEmail', 'email')">Invalid mail address</md-hint-->
    </md-input-container>
    <md-input-container class="col-md-6 md-icon-left no-margin-bottom">
        <md-icon class="material-icons">lock_outline</md-icon>
        <input required mdInput formControlName="password" type="password" class="form-control" id="password" name="password" placeholder="Contraseña">
    </md-input-container>
    <md-input-container class="col-md-6 md-icon-left no-margin-bottom">
        <md-icon class="material-icons">lock_outline</md-icon>
        <input required mdInput type="password" formControlName="confirmPassword" class="form-control" name="password" placeholder="Confirmar Contraseña">
    </md-input-container>
</div>
<button md-raised-button type="submit">Siguiente</button>

所以,我有两个问题。第一个是如何修复我正在尝试验证密码和电子邮件的错误。第二个是知道如果嵌套表单(emailPass表单)无效,我如何禁用该按钮。

感谢您一如既往的帮助!

1 个答案:

答案 0 :(得分:2)

请查看this answer我提供了一个几乎相似的问题,比较了两个同级的formControls。

基于此,

import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms";

function isEqualPassword(control: AbstractControl): {[s: string]: boolean} {
 if (!control.get('password') || !control.get('confirmPassword')) {
   return null; // returning validity true if either one of the controls not present - safety check on initial load
 }
 return control.get('password').value === control.get('confirmPassword').value ? null : {passwordsNotMatch: true};
}

@Component({
  selector: 'my-page-sign-up',
  styleUrls: ['./sign-up.component.scss'],
  templateUrl: './sign-up.component.html'
})

export class PageSignUpComponent implements OnInit {

 myForm: FormGroup;

 constructor(private fb: FormBuilder) {
   this.myForm = this.fb.group({
     emailPass: this.fb.group({
       email: ['', [
         Validators.required,
         Validators.email
       ]],
       passwordsCtrl: this.fb.group({
         password: ['', Validators.required],
         confirmPassword: ['', Validators.required]
         }, { validator: isEqualPassword }
       })
     })
   })
 }     
}

然后将您的密码相关控件包装在另一个div或类似的(您的选择)另一个formGroupName中,以表示这两个控件的新创建的包装formGroup。

<form [formGroup]="myForm" (ngSubmit)="onSignup()">
<div formGroupName="emailPass" class="form-group">
    <md-input-container class="col-md-6 md-icon-left">
        <md-icon class="material-icons">mail_outline</md-icon>
        <input formControlName="email" mdInput #email type="email" name="email" class="form-control" placeholder="Email">
        <!--md-hint *ngIf="!myForm.get(['emailPass', 'email']).pristine && myForm.hasError('noEmail', 'email')">Invalid mail address</md-hint-->
    </md-input-container>
    <div formGroupName="passwordsCtrl">
     <md-input-container class="col-md-6 md-icon-left no-margin-bottom">
         <md-icon class="material-icons">lock_outline</md-icon>
         <input required mdInput formControlName="password" type="password" class="form-control" id="password" name="password" placeholder="Contraseña">
     </md-input-container>
     <md-input-container class="col-md-6 md-icon-left no-margin-bottom">
         <md-icon class="material-icons">lock_outline</md-icon>
         <input required mdInput type="password" formControlName="confirmPassword" class="form-control" name="password" placeholder="Confirmar Contraseña">
     </md-input-container>
    </div>
</div>
<button md-raised-button type="submit">Siguiente</button>

关于禁用该按钮,您的myFormemailPass formGroups基本相同。如果这就是你的形式,你也可以省略其中一个。因此,您可以使用valid的{​​{1}}标记或特定的myForm formGroup来检查表单的有效性,

emailPass

<button md-raised-button type="submit" [disabled]="!myForm.valid">Siguiente</button>

希望它有所帮助。