Angular 2 / Material - 应用到父 FormGroup 的自定义验证器未显示 md 错误

     2023-03-13     37

关键词:

【中文标题】Angular 2 / Material - 应用到父 FormGroup 的自定义验证器未显示 md 错误【英文标题】:Angular 2 / Material - md-error not displayed with custom validator applied to parent FormGroup 【发布时间】:2018-03-02 00:01:12 【问题描述】:

我在使用 Angular (v4.3.6) 在模型驱动表单上显示验证错误时遇到了一些麻烦。

在我的模型中,我有以下内容:

this.registerForm = formBuilder.group(
        'email':[null,Validators.compose([Validators.required, ValidateEmail])],
        'firstName':[null, Validators.required],
        'lastName':[null, Validators.required],
        'passwordGroup': formBuilder.group(
            'password':[null, Validators.compose([Validators.required,Validators.minLength(8)])],
            'passwordConfirmation':[null, Validators.required],
        ,validator: ValidatePasswordConfirmation)
    );

引用的ValidatePasswordConfirmation自定义验证器如下:

export function ValidatePasswordConfirmation(group: FormGroup) 

    if(group.value.password !== group.value.passwordConfirmation)
        return  'no-match':true ;
    

    return null;

最后,在我的模板中,我有以下内容:

<md-form-field>
  <input mdInput name="passwordConfirmation" placeholder="Confirm password" [formControl]="registerForm.controls['passwordGroup'].controls['passwordConfirmation']" [(ngModel)]="model.passwordConfirmation" type="password">

<md-error *ngIf="registerForm.controls['passwordGroup'].controls['passwordConfirmation'].hasError('required')">
    Password confirmation is required
  </md-error>

<md-error *ngIf="registerForm.controls['passwordGroup'].hasError('no-match')">
    Passwords don't match
  </md-error>

</md-form-field>

但是,由“不匹配”错误控制的 md 错误永远不会出现。因此,为了在页面上进行调试,我添加了以下内容:

no-match = registerForm.controls['passwordGroup'].hasError('no-match') 
invalid = registerForm.controls['passwordGroup'].invalid

不出所料,调试行显示真/假,如您所料。但是,永远不会显示“md-error”……除非显示“必需”错误。我有一种感觉,问题是由于 [formControl] 引用了 passwordConfirmation FormControl,因此如果它无效,则不会显示 md 错误。但是,我希望在外部 FormGroup 无效时显示此错误。

任何关于我在哪里出错的指示都会非常有帮助!

最后,我尝试了其他一些方法,例如在 PasswordConfirmation FormControl 上设置错误,这可行,但我想知道为什么我当前的实现失败了。

【问题讨论】:

【参考方案1】:

我发现我能够使用自定义 ErrorStateMatcher 解决完全相同的问题(默认的要求控件在显示任何错误之前处于无效状态)

export class ParentErrorStateMatcher implements ErrorStateMatcher 
    isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean 
        const isSubmitted = !!(form && form.submitted);
        const controlTouched = !!(control && (control.dirty || control.touched));
        const controlInvalid = !!(control && control.invalid);
        const parentInvalid = !!(control && control.parent && control.parent.invalid && (control.parent.dirty || control.parent.touched));

        return isSubmitted || (controlTouched && (controlInvalid || parentInvalid));
    

这在我的页面组件上作为变量公开,就像这样......

@Component(
    templateUrl: 'register.page.component.html',
    styleUrls: ['register.page.styles.css']
)
export class RegisterPageComponent implements OnInit 
    registerForm: FormGroup;
    parentErrorStateMatcher = new ParentErrorStateMatcher();

    // Accessors
    get name()  return this.registerForm.get('name'); 
    get email()  return this.registerForm.get('email'); 
    get passwords()  return this.registerForm.get('passwords'); 
    get password()  return this.registerForm.get('passwords.password'); 
    get confirmPassword()  return this.registerForm.get('passwords.confirmPassword'); 
...

有了这个表格...

this.registerForm = this.formBuilder.group(
        name: ['', [
            Validators.required,
            Validators.maxLength(256)]
        ],
        email: ['', [
            Validators.email,
            Validators.required,
            Validators.maxLength(256)]
        ],
        passwords: this.formBuilder.group(
            password: ['', [
                Validators.required,
                Validators.maxLength(128)
            ]],
            confirmPassword: ['', [
                Validators.required
            ]]
        ,
            
                validator: CustomValidators.doNotMatch('password', 'confirmPassword')
            ),
    );

还有密码字段的这个标记(参见 errorStateMatcher 和 confirmPassword 输入控件的最后一个 mat-error)...

<div formGroupName="passwords">
    <mat-form-field class="full-width">
        <input matInput placeholder="Password" type="password" name="password" id="password" formControlName="password" required/>
        <mat-error *ngIf="password.errors && password.errors.required">
            Please enter your password
        </mat-error>
        <mat-error *ngIf="password.errors && password.errors.maxLength">
            Password must be less than 128 characters long
        </mat-error>
    </mat-form-field>

    <mat-form-field class="full-width">
        <input matInput placeholder="Confirm Password" type="password" name="confirmPassword" id="confirmPassword" formControlName="confirmPassword" required
            [errorStateMatcher]="parentErrorStateMatcher"/>
        <mat-error *ngIf="confirmPassword.errors && confirmPassword.errors.required">
            Please confirm your password
        </mat-error>
        <mat-error *ngIf="passwords.errors && passwords.errors.doNotMatch">
            Passwords do not match
        </mat-error>
    </mat-form-field>
</div>

感觉比我不使用 Material 时更加混乱,但我很高兴能够权衡取舍,而且真正唯一的额外代码是自定义匹配器 :)

【讨论】:

【参考方案2】:

在我的情况下,这段代码运行良好。代码结构如下:

// component.ts
import  FormBuilder, FormGroup, FormControl, Validators  from '@angular/forms';

function validate(v: FormGroup): any 
  let a = k.get('a');
  let b = k.get('b');
  if (a.value != undefined && (b.value == undefined || a.value == "none" || b.value == " ")) 
    return  ab: true ;
  
  return null;


@Component(
)

export class component implements OnInit, OnDestroy 
  constructor()
  ngOnInit() 
    this.registerForm = formBuilder.group(
        'email':[null,Validators.compose([Validators.required, ValidateEmail])],
        'firstName':[null, Validators.required],
        'lastName':[null, Validators.required],
        'passwordGroup': formBuilder.group(
            'password':[null, Validators.compose([Validators.required,Validators.minLength(8)])],
            'passwordConfirmation':[null, Validators.required],
        ,validator: ValidatePasswordConfirmation)
    );
  

如果条件出现 HTML 错误消息显示,其使用方式与上述代码中相同。

【讨论】:

可以包含你的 html 吗? HTML 错误信息【参考方案3】:

我已经在 Angular Material 输入上使用 ,validator: ValidatePasswordConfirmation 等自定义验证遇到了这个问题,这似乎是 Material 的问题。这是我在 Angular Material 页面上的问题:https://github.com/angular/material2/issues/7084。它没有答案,所以问题仍然存在。我的决定是在提交表单后使用验证,它不是很漂亮和正确,但它正在工作。希望下个版本能解决这个问题。

或者,如果您想要实时验证,您可以执行以下操作:

checkArePasswordsValid() 
    this.passwordsAreEqual = this.passwordValue === this.passwordConfirmationValue ? true : false;

并使用此布尔值进行验证。

【讨论】:

Angular 2 / Material - 应用到父 FormGroup 的自定义验证器未显示 md 错误

】Angular2/Material-应用到父FormGroup的自定义验证器未显示md错误【英文标题】:Angular2/Material-md-errornotdisplayedwithcustomvalidatorappliedtoparentFormGroup【发布时间】:2018-03-0200:01:12【问题描述】:我在使用Angular(v4.3.6)在模型驱动表单上显示... 查看详情

Angular 2 Material无法加载样式

】Angular2Material无法加载样式【英文标题】:Angular2Materialcan\'tloadstyle【发布时间】:2017-10-0411:06:26【问题描述】:我开始在Angular中使用AngularMaterial库为界面开发一个Web应用程序。但是在尝试导入预建主题时出现错误。为了导入它... 查看详情

angular-material2 工具栏阴影

】angular-material2工具栏阴影【英文标题】:angular-material2toolbarshadow【发布时间】:2017-07-1322:07:27【问题描述】:我是material2的新手我试图将主应用程序工具栏固定在屏幕顶部,问题是海拔无法正常工作(内容隐藏了工具栏的阴影... 查看详情

Angular 2.0 Material MdDialog 与 Angular 2.0 的工作示例

】Angular2.0MaterialMdDialog与Angular2.0的工作示例【英文标题】:WorkingexampleofAngular2.0MaterialMdDialogwithAngular2.0【发布时间】:2016-03-1607:22:12【问题描述】:我正在开发POC应用程序,并且正在尝试使MdDialog组件正常工作。有没有人有一个... 查看详情

Angular Material 2:修复多行错误消息

】AngularMaterial2:修复多行错误消息【英文标题】:AngularMaterial2:FixforMultilineErrormessages【发布时间】:2018-02-1805:34:39【问题描述】:我在我的Angular应用程序中使用了AngularMaterial2。当我的表单输入字段错误消息超过一行时,我遇到... 查看详情

波纹效果未显示在角度应用程序的按钮中 - Angular-Material

】波纹效果未显示在角度应用程序的按钮中-Angular-Material【英文标题】:Rippleeffectisnotdisplayinginbuttoninangularapp-Angular-Material【发布时间】:2019-05-1117:32:35【问题描述】:https://material.angular.io/components/button/overview我正在使用这个angula... 查看详情

Angular 2 Material - 如何居中进度微调器

】Angular2Material-如何居中进度微调器【英文标题】:Angular2Material-HowToCenterProgressSpinner【发布时间】:2017-05-1406:34:32【问题描述】:我已经从下面的链接实现了Angular2进度微调器https://github.com/angular/material2/tree/master/src/lib/progress-spin... 查看详情

Angular 4 Material - 垫子按钮样式未应用于垫子对话框组件

】Angular4Material-垫子按钮样式未应用于垫子对话框组件【英文标题】:Angular4Material-mat-buttonstylenotbeingappliedinmat-dialogcomponent【发布时间】:2018-04-1411:54:48【问题描述】:我想创建一个带有默认样式mat-button的mat-dialog来关闭对话框。... 查看详情

Angular 2 routerlink 在 Material 2 Toolbar 中不可点击

】Angular2routerlink在Material2Toolbar中不可点击【英文标题】:Angular2routerlinknotclickableinMaterial2Toolbar【发布时间】:2017-04-2116:45:16【问题描述】:routerLink指令在Material2的md-toolbar组件中无效。toolbar.component.html:<md-toolbarcolor="primary"& 查看详情

Angular Material 2 Textarea Autosize 属性 (mdTextareaAutosize)

】AngularMaterial2TextareaAutosize属性(mdTextareaAutosize)【英文标题】:AngularMaterial2TextareaAutosizeAttribute(mdTextareaAutosize)【发布时间】:2017-09-1411:03:25【问题描述】:我正在使用@angular/material@2.0.0-beta.2。我在带有display:none(弹出窗口)的容... 查看详情

Angular 5 Angular Material 2 - 使用 minLength 自动完成

】Angular5AngularMaterial2-使用minLength自动完成【英文标题】:Angular5AngularMaterial2-autocompletewithminLength【发布时间】:2018-10-1917:03:41【问题描述】:我在表单上添加了自动完成字段以选择患者。患者数据来自数据库。问题是有40.000名患... 查看详情

如何让 Angular Material Icon 在我的 Angular 应用程序中显示轮廓?

】如何让AngularMaterialIcon在我的Angular应用程序中显示轮廓?【英文标题】:HowcanIgetAngularMaterialIcontoshowtheoutlineinmyAngularapp?【发布时间】:2018-10-2518:37:00【问题描述】:我现在有<mat-icon>info<mat-icon>它给出了填充颜色的信息... 查看详情

如何将给定的指令值应用于 Angular Material 中的多个标签?

】如何将给定的指令值应用于AngularMaterial中的多个标签?【英文标题】:HowtoapplyagivendirectivevaluetomultipletagsinAngularMaterial?【发布时间】:2021-07-1114:08:56【问题描述】:我最近开始学习Angular和Material,在我的项目中我意识到我必须... 查看详情

Angular Material 未锁定侧边栏

】AngularMaterial未锁定侧边栏【英文标题】:AngularMaterialNotLockedsidebar【发布时间】:2016-03-0111:37:15【问题描述】:我有一个这样的侧边栏:按钮1按钮2此入门应用程序由工具栏、SideNav(带有两个按钮)和内容区域组成。这是内容... 查看详情

如何从 angular-material2 对话框与其父级进行通信

】如何从angular-material2对话框与其父级进行通信【英文标题】:Howtocommunicatefromangular-material2dialogtoitsparent【发布时间】:2017-07-3117:54:59【问题描述】:我有一个Parent组件,它打开了一个angular-material2对话框。letdialogRef=this.dialog.open... 查看详情

Angular 2 Material - 如何有条件地设置工具栏的颜色

】Angular2Material-如何有条件地设置工具栏的颜色【英文标题】:Angular2Material-howtosetthecolorofatoolbarconditionally【发布时间】:2017-07-2020:01:27【问题描述】:我正在使用AngularMaterialtoolbar,它可以有三种颜色:“primary”、“accent”或“... 查看详情

尝试从 npm 安装 Angular 2 Material - 源文本中无法识别的标记

】尝试从npm安装Angular2Material-源文本中无法识别的标记【英文标题】:TryingtoinstallAngular2Materialfromnpm-unrecognizedtokeninsourcetext【发布时间】:2016-10-2816:07:31【问题描述】:我从PowerShell(以管理员身份)尝试以下命令npminstall@angular2-ma... 查看详情

Angular Material 2 Form 不显示

】AngularMaterial2Form不显示【英文标题】:AngularMaterial2Formdoesnotdisplay【发布时间】:2018-06-0223:00:43【问题描述】:我正在尝试按照Material2网站中的说明添加表单和输入。表单不显示,但是当我单击表单输入时它会显示。附加信息(... 查看详情