
本文介绍了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-browser';从'@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-browser/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+,为什么材料不想显示错误信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!