本文介绍了Angular 2+,为什么材料不想显示错误信息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想确认密码,但是当我写了验证器的逻辑并将其发送到mat-error时,消息没有显示,但验证器工作正常,此时如何解决在我的情况下以反应形式??

导出类 SignUpComponent 实现 OnInit {profileForm:FormGroup;构造函数(私人用户服务:用户服务,私有表单构建器:FormBuilder){this.profileForm = this.formBuilder.group({名称:['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_ -]+$/)]],电子邮件:['', [Validators.required, Validators.pattern(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)]],密码:['', [Validators.required, Validators.pattern(/^(?=.*[A-Z])(?=.*\d)(.{8,100})$/)]],密码确认:['', [Validators.required]]},{ 验证器:this.checkPasswords });}checkPasswords(组:FormGroup){let pass = group.get('password').value;let confirmPass = group.get('passwordConfirm').value;返回通行证 === 确认通行证?空:{不匹配:真}}ngOnInit() {}获取名称(){返回 this.profileForm.get('name');}获取电子邮件(){返回 this.profileForm.get('email');}获取密码(){返回 this.profileForm.get('密码')}获取密码确认(){返回 this.profileForm.get('passwordConfirm')}提交(){console.warn(this.profileForm.value);this.userService.createUser(this.profileForm.value);}}

在html代码中

<div class="form-input-position"><mat-form-field class="example-full-width" ><input matInput placeholder="Name" formControlName="name" required><mat-icon matSuffix>Supervised_user_circle</mat-icon><mat-error *ngIf="name.hasError('required')">字段应该是必填;</mat-error><mat-error *ngIf="name.hasError('pattern')">字段应使用<strong>拉丁字母</strong></mat-error></mat-form-field>

<div class="form-input-position"><mat-form-field class="example-full-width" ><input matInput placeholder="Email" formControlName="email" required><mat-icon matSuffix>电子邮件</mat-icon><mat-error *ngIf="email.hasError('required')">字段应该是必填;</mat-error><mat-error *ngIf="email.hasError('pattern')">使用正确的<strong>电子邮件格式</strong></mat-error></mat-form-field>

<div class="form-input-position"><mat-form-field class="example-full-width" ><input matInput type="password" placeholder="Password" formControlName="password" required><mat-icon matSuffix>lock</mat-icon><mat-error *ngIf="password.hasError('required')">字段应该是必填;</mat-error><mat-error *ngIf="password.hasError('pattern')">应该是<strong>最少8个元素,一个大写字母,一个数字</strong></mat-error></mat-form-field>

<div class="form-input-position"><mat-form-field class="example-full-width" ><input matInput type="password" placeholder="Confirm password" formControlName="passwordConfirm" required><mat-icon matSuffix>lock</mat-icon><mat-error *ngIf="passwordConfirm.hasError('required')">字段应该是必填;</mat-error>{{profileForm.hasError('mismatch')}}<mat-error *ngIf="profileForm.hasError('mismatch')">密码<strong>mistmached</strong></mat-error></mat-form-field>

<div class="form-input-button"><button mat-raised-button color="accent" [disabled]="!profileForm.valid" type="submit">Submit</button><button mat-raised-button color="warn">取消</button>

</表单>

这种情况我已经尝试过(在 Angular 6 中确认密码验证 解决方案) 但错误的问题:

未捕获的错误:意外的值SignUpComponent"由模块AppModule".请添加@Pipe/@Directive/@Component注释.

如果我是对的,它是 模板驱动的表单 不是反应式的方式

节点

我的app.modul.ts文件

import { BrowserModule } from '@angular/platform-b​​rowser';从'@angular/core' 导入 { NgModule };从'@angular/common/http'导入{HttpClientModule};import { AppRoutingModule } from './app-routing.module';从 './app.component' 导入 { AppComponent };import { SignUpComponent } from './sign-up/sign-up.component';从@angular/platform-b​​rowser/animations"导入 { BrowserAnimationsModule };从@angular/forms"导入 { FormsModule, ReactiveFormsModule };导入 { MatIconModule,垫菜单模块,垫输入模块,垫按钮模块来自'@angular/material';从 './login/login.component' 导入 { LoginComponent };从 './home/home.component' 导入 { HomeComponent };@NgModule({声明: [应用组件,注册组件,登录组件,主页组件],进口:[浏览器模块,表单模块,应用路由模块,浏览器动画模块,垫菜单模块,MatIcon模块,垫输入模块,垫按钮模块,反应形式模块,HttpClient 模块],提供者:[],引导程序:[AppComponent]})导出类 AppModule { }

节点 2

我已阅读https://itnext.io/materror-cross-field-validators-in-angular-material-7-97053b2ed0cf

还有这个 https://material.angular.io/components/input/overview#changed-when-error-messages-are-shown

此链接介绍了用于触摸输入的 ErrorStateMatcher 实现.好吧,我改变了我的代码

在注册.component.ts

导出类 MyErrorStateMatcher 实现 ErrorStateMatcher {isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {返回 control.dirty &&表单.无效;}}

如果我们开始在输入中输入内容,而表单本身无效,请说明控件有错误.

创建对象 errorMatcher = new MyErrorStateMatcher(); 登录 class SignUpComponent

我在 ts 文件中的表单看起来像

this.profileForm = this.formBuilder.group({名称:['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_ -]+$/)]],电子邮件:['', [Validators.required, Validators.pattern(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)]],密码:['', [Validators.required, Validators.pattern(/^(?=.*[A-Z])(?=.*\d)(.{8,100})$/)]],确认密码: ['']},{ 验证器:this.passwordValidator });}密码验证器(形式:FormGroup){const condition = form.get('password').value !== form.get('verifyPassword').value;退货条件?{ passwordsDoNotMatch: true} : null;}

最后是 html 文件

<mat-icon matSuffix>lock</mat-icon><mat-error *ngIf="passwordConfirm.hasError('required')">字段应该是必填;</mat-error>{{profileForm.hasError('mismatch')}}<mat-error*ngIf="profileForm.hasError('passwordsDoNotMatch')">字段应为<strong>AAAAA</strong></mat-error><p*ngIf="profileForm.hasError('passwordsDoNotMatch')">aaaaaaaaaaaaaaa</p>

但是,我有一个大问题,无法下载表单

compiler.js:2175 未捕获的错误:模块AppModule"声明的意外值SignUpComponent".请添加@Pipe/@Directive/@Component 注解.

我已经尝试修复它(添加到@NgModule 下一行)

 提供者:[{ 提供:ErrorStateMatcher,useClass:ShowOnDirtyErrorStateMatcher }],

但这对我没有帮助

解决方案

*更新

要在控件上创建 customFormControl,我们使用 parent,参见示例

checkPasswords(): ValidatorFn {//看到参数是一个FormControl返回(控件:FormControl):ValidationErrors =>{//表单组是control.parentconst group = control.parent as FormGroup;//但我们必须确保已定义if (!group) 返回空值;console.log(group.get("password").value);let pass = group.get("password").value;let confirmPass = group.get("passwordConfirm").value;返回确认通行证?通过 === 确认通过?空:{不匹配:真}:空;};}

因为我们也想在密码更改时进行检查

ngOnInit() {this.form.get("password").valueChanges.subscribe(() => {this.form.get("passwordConfirm").updateValueAndValidity();});}

看表格是这样的

form = new FormGroup({密码:new FormControl("", Validators.required),密码确认:new FormControl("", [Validators.required,this.checkPasswords()])});

和 .html

<mat-form-field class="example-full-width"><input matInput placeholder="password" formControlName="password"><mat-error >必需的</mat-error></mat-form-field><mat-form-field class="example-full-width"><input matInput placeholder="重复密码" formControlName="passwordConfirm"><mat-error *ngIf="form.get('passwordConfirm').hasError('mismatch')">必须匹配器</mat-error><mat-error *ngIf="form.get('passwordConfirm').hasError('required')">必需的</mat-error></mat-form-field></表单>

stackblitz 这里

另一种方式是使用自定义的 errorStateMatcher

更新 2 我说过另一种方法是使用 errorStateMatcher".erroStateMatcher 是一个返回 true 或 false 的简单函数.如果返回true,我们的控件将被标记为无效(*)

想象一下我们有一个像

form = new FormGroup({密码:new FormControl("", Validators.required),密码确认:new FormControl("", [Validators.required,])},this.checkPasswords());

看到错误属于formGroup,我们可以创建一个customErrorMatcher,如果控件无效或form.hasError('mismatch`)返回true

导出类 MyErrorStateMatcher 实现 ErrorStateMatcher {isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {return !!((control && form.hasError('mismatch') || control.invalid) && control.touched );}}

嗯,.html

<mat-form-field class="example-full-width"><input matInput placeholder="password" formControlName="password"><mat-error >必需的</mat-error></mat-form-field><!--看到errorStateMatcher"应用于输入passwordConfirm"--><mat-form-field class="example-full-width"><input matInput placeholder="重复密码" formControlName="passwordConfirm"[errorStateMatcher]="匹配器"><!--这里显示的错误是form.hasError('mismatch')--><mat-error *ngIf="form.hasError('mismatch')">必须匹配器</mat-error><!--这里显示的错误是 form.get('passwordConfirm').hasError--><mat-error *ngIf="form.get('passwordConfirm').hasError('required')">必需的</mat-error></mat-form-field></表单>

一如既往,堆栈闪电战

(*) 检查 stackblitz 表单.get('passwordConfirm').invalid

I want to confirm the passwords, but when I wrote the logic of validator and send it to the mat-error the message haven't shown, but the validator work normally, how fix this moment in reactive forms in my case??

export class SignUpComponent implements OnInit {

  profileForm: FormGroup;

  constructor(
     private userService: UserService,
     private formBuilder: FormBuilder
  ) {
    this.profileForm = this.formBuilder.group({
      name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_ -]+$/)]],
      email: ['', [Validators.required, Validators.pattern(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)]],
  password: ['', [Validators.required, Validators.pattern(/^(?=.*[A-Z])(?=.*\d)(.{8,100})$/)]],
      passwordConfirm: ['', [Validators.required]]
    },
      { validator: this.checkPasswords }
    );
  }

  checkPasswords(group: FormGroup) {
    let pass = group.get('password').value;
    let confirmPass = group.get('passwordConfirm').value;

    return pass === confirmPass ? null : { mismatch: true }
  }

  ngOnInit() {
  }

  get name(){
    return this.profileForm.get('name');
  }

  get email(){
    return this.profileForm.get('email');
  }

  get password(){
    return this.profileForm.get('password')
  }

  get passwordConfirm(){
    return this.profileForm.get('passwordConfirm')
  }

  onSubmit() {
    console.warn(this.profileForm.value);
    this.userService.createUser(this.profileForm.value);
  }

}

in html code

<form class="form-to-submit" [formGroup]="profileForm" (ngSubmit)="onSubmit()">

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput placeholder="Name" formControlName="name" required>
                <mat-icon matSuffix>supervised_user_circle</mat-icon>

                <mat-error *ngIf="name.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>
                <mat-error *ngIf="name.hasError('pattern')">
                    Field should use <strong>Latin alphabet</strong>
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput placeholder="Email" formControlName="email" required>
                <mat-icon matSuffix>email</mat-icon>

                <mat-error *ngIf="email.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>
                <mat-error *ngIf="email.hasError('pattern')">
                    Use right <strong>email format</strong>
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput type="password" placeholder="Password" formControlName="password" required>
                <mat-icon matSuffix>lock</mat-icon>

                <mat-error *ngIf="password.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>
                <mat-error *ngIf="password.hasError('pattern')">
                    Should be <strong>minimum 8 elements, one uppercase letter, one number</strong>
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput type="password" placeholder="Confirm password" formControlName="passwordConfirm" required>
                <mat-icon matSuffix>lock</mat-icon>

                <mat-error *ngIf="passwordConfirm.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>

                {{profileForm.hasError('mismatch')}}
                <mat-error *ngIf="profileForm.hasError('mismatch')">
                    Password <strong>mistmached</strong>
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-button">
            <button mat-raised-button color="accent" [disabled]="!profileForm.valid" type="submit">Submit</button>
            <button mat-raised-button color="warn">Cancel</button>
        </div>


    </form>

this case I have tried (Confirm password validation in Angular 6 solution) but the problem in error:

and if I am right it is template-driven forms not a reactive way

Node

my app.modul.ts file

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SignUpComponent } from './sign-up/sign-up.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { MatIconModule,
     MatMenuModule,
     MatInputModule,
     MatButtonModule
     } from '@angular/material';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';

@NgModule({
  declarations: [
AppComponent,
SignUpComponent,
LoginComponent,
HomeComponent
  ],
  imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
BrowserAnimationsModule,
MatMenuModule,
MatIconModule,
MatInputModule,
MatButtonModule,
ReactiveFormsModule,
HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Node 2

I have read the https://itnext.io/materror-cross-field-validators-in-angular-material-7-97053b2ed0cf

and this https://material.angular.io/components/input/overview#changing-when-error-messages-are-shown

this links told about the ErrorStateMatcher implementation to touch the input. Well I changed my code

in sign-up.component.ts

export class MyErrorStateMatcher implements ErrorStateMatcher {
   isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
  return control.dirty && form.invalid;
  }
}

create the object errorMatcher = new MyErrorStateMatcher(); in sign in class SignUpComponent

my form in ts file looks like

this.profileForm = this.formBuilder.group({
  name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_ -]+$/)]],
  email: ['', [Validators.required, Validators.pattern(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)]],
  password: ['', [Validators.required, Validators.pattern(/^(?=.*[A-Z])(?=.*\d)(.{8,100})$/)]],
  passwordConfirm: ['']
},
  { validator: this.passwordValidator }
);
}

passwordValidator(form: FormGroup) {
  const condition = form.get('password').value !== form.get('verifyPassword').value;

  return condition ? { passwordsDoNotMatch: true} : null;
}

and finally html file

<input matInput type="password" placeholder="Confirm password" formControlName="passwordConfirm" required
                       [errorStateMatcher]="matcher">
                <mat-icon matSuffix>lock</mat-icon>

                <mat-error *ngIf="passwordConfirm.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>

                {{profileForm.hasError('mismatch')}}
                <mat-error
*ngIf="profileForm.hasError('passwordsDoNotMatch')">
                    Field should be <strong>AAAAA</strong>
                </mat-error>
                <p
*ngIf="profileForm.hasError('passwordsDoNotMatch')">aaaaaaaaaaaaaaaa</p>

However, I have a big problem which stop downloading form

I've tried to fix it (add to @NgModule next lines)

 providers: [
{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }
 ],

but it didn't help me

解决方案

*Update

To create a customFormControl over a control, we use parent, see an example

checkPasswords(): ValidatorFn {
    //see that the argument is a FormControl
    return (control: FormControl): ValidationErrors => {
      //the formGroup is control.parent
      const group = control.parent as FormGroup;
      //but we must sure that is defined
      if (!group) return null;
      console.log(group.get("password").value);
      let pass = group.get("password").value;
      let confirmPass = group.get("passwordConfirm").value;

      return confirmPass ? pass === confirmPass ? null : { mismatch: true } : null;
    };
  }

As we want to make check when password change too

ngOnInit() {
    this.form.get("password").valueChanges.subscribe(() => {
      this.form.get("passwordConfirm").updateValueAndValidity();
    });
  }

See that the form is like

form = new FormGroup({
    password: new FormControl("", Validators.required),
    passwordConfirm: new FormControl("", [
      Validators.required,
      this.checkPasswords()
    ])
  });

And the .html

<form [formGroup]="form" class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="password" formControlName="password">
        <mat-error >
      required
    </mat-error>

  </mat-form-field>
  <mat-form-field class="example-full-width">
    <input matInput placeholder="repeat password" formControlName="passwordConfirm"
           >
    <mat-error *ngIf="form.get('passwordConfirm').hasError('mismatch')">
      must matcher
    </mat-error>
    <mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
      required
    </mat-error>
  </mat-form-field>
</form>

The stackblitz here

The other way is using a custom errorStateMatcher

Update 2 I said that other way is "use a errorStateMatcher." A erroStateMatcher is a simple function that return true or false. If return true, our control will be marked as if he was invalid(*)

Imagine we has a form like

form = new FormGroup({
    password: new FormControl("", Validators.required),
    passwordConfirm: new FormControl("", [
      Validators.required,

    ])
  },this.checkPasswords());

See that error is belong to formGroup, we can create a customErrorMatcher that return true if control is invalid or if form.hasError('mismatch`)

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return !!((control && form.hasError('mismatch') || control.invalid) && control.touched );
  }
}

Well, the .html

<form [formGroup]="form" class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="password" formControlName="password">
        <mat-error >
      required
    </mat-error>

  </mat-form-field>
<!--see that the "errorStateMatcher" is applied to the input "passwordConfirm"-->
  <mat-form-field class="example-full-width">
    <input matInput placeholder="repeat password" formControlName="passwordConfirm"
    [errorStateMatcher]="matcher"
           >
      <!--here show the error is form.hasError('mismatch')-->
    <mat-error *ngIf="form.hasError('mismatch')">
      must matcher
    </mat-error>
       <!--here show the error is form.get('passwordConfirm').hasError-->
    <mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
      required
    </mat-error>
  </mat-form-field>
</form>

As always I can, the stackblitz

(*) check in the stackblitz form.get('passwordConfirm').invalid

这篇关于Angular 2+,为什么材料不想显示错误信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 19:27
查看更多