【问题标题】:Can't access to nested forms values to validate form无法访问嵌套表单值来验证表单
【发布时间】:2018-03-11 12:02:27
【问题描述】:

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

组件.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 表单)无效,我该如何禁用按钮。

感谢您一如既往的帮助!

【问题讨论】:

    标签: angular typescript angular-reactive-forms


    【解决方案1】:

    请查看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>
    

    关于禁用按钮,您的myForm 和emailPass formGroups 基本相同。如果这就是您的表格中的全部内容,您也可以省略两者中的任何一个。因此,您可以像这样使用myForm 的valid 标志或特定的emailPass formGroup 来检查表单的有效性,

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

    或

    <button md-raised-button type="submit" [disabled]="!myForm.get('emailPass').valid">Siguiente</button>
    

    希望对你有帮助。

    【讨论】:

    • 嗨@amal。首先感谢您的帮助,但代码不起作用。您提供的代码中似乎存在一些打字错误。我试图解决这个问题,但等于密码的功能不起作用。顺便说一句,我想这里应该说(!control.get('password')而不是(!c.get('password')。我发现的另一个问题是无法读取 html 中未定义的 emailPass 的属性“有效”
    • 是的,你是对的。我从其他参考文献中复制我的答案时错过了
    • 更新了我的答案。它应该可能会为您修复它。请参阅最后一个 button 代码行,其中您引用了 emailPass 的 valid 属性。
    • 非常感谢@amal。有效。我已经将问题标记为已回答,但是请您再帮我做一件事吗?我怎样才能使这部分工作? &lt;md-hint *ngIf="!myForm.get(['emailPass', 'email']).pristine &amp;&amp; myForm.get(['emailPass', 'email']).hasError('noEmail', 'email')"&gt;Invalid mail address&lt;/md-hint&gt;
    • 如果您只想在 email 字段为空或格式无效时显示一般错误消息,那么应该这样做。 &lt;md-hint *ngIf="!myForm.get(['emailPass', 'email']).pristine &amp;&amp; myForm.get(['emailPass', 'email']).errors"&gt;Invalid mail address&lt;/md-hint&gt;
    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    相关资源
    最近更新 更多