我的页面上有一个表单,当我致电FormGroup.reset()
时,它会将表单类设置为ng-pristine ng-untouched
,但FormControl.hasError(...)
仍会返回真值。我在这里做错了什么?
模板
<form [formGroup]="myForm" (ngSubmit)="submitForm(myForm)">
<mat-form-field>
<input matInput formControlName="email" />
<mat-error *ngIf="email.hasError('required')">
Email is a required feild
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" formControlName="password" />
<mat-error *ngIf="password.hasError('required')">
Password is a required feild
</mat-error>
</mat-form-field>
<button type="submit">Login</button>
</form>
组件
export class MyComponent {
private myForm: FormGroup;
private email: FormControl = new FormContorl('', Validators.required);
private password: FormControl = new FormControl('', Validators.required);
constructor(
private formBuilder: FormBuilder
) {
this.myForm = formBuilder.group({
email: this.email,
password: this.password
});
}
private submitForm(formData: any): void {
this.myForm.reset();
}
}
Plunker
答案 0 :(得分:73)
它(FormGroup
)行为正确。您的表单需要用户名和密码,因此当您重置表单时,它应该是无效的(即没有用户名/密码的表单无效)。
如果我理解正确,那么您的问题就是为什么在您第一次加载页面时(表单无效时)没有出现红色错误,但单击按钮时弹出错误。当您使用Material时,此问题尤为突出。
AFAIK,<mat-error>
检查FormGroupDirective
的有效性,而非FormGroup
的有效性,重置FormGroup
不会重置FormGroupDirective
。这有点不方便,但要清除<mat-error>
,您还需要重置FormGroupDirective
。
为此,在模板中定义一个变量:
<form [formGroup]="myForm" #formDirective="ngForm"
(ngSubmit)="submitForm(myForm, formDirective)">
在您的组件类中,请致电formDirective.resetForm()
:
private submitForm(formData: any, formDirective: FormGroupDirective): void {
formDirective.resetForm();
this.myForm.reset();
}
答案 1 :(得分:8)
resetForm() {
this.loginForm.reset();
for( let i in this.loginForm.controls ) {
this.loginForm.controls[i].setErrors(null);
}
}
答案 2 :(得分:6)
除了Harry Ninh的解决方案之外,如果您想在组件中访问formDirective而不需要选择表单按钮,则:
模板:
<form
...
#formDirective="ngForm"
>
组件:
import { ViewChild, ... } from '@angular/core';
import { NgForm, ... } from '@angular/forms';
export class MyComponent {
...
@ViewChild('formDirective') private formDirective: NgForm;
constructor(... )
private someFunction(): void {
...
formDirective.resetForm();
}
}
答案 3 :(得分:2)
2021 年更新 - ANGULAR 11.2
直接在 HTML 函数中使用 [formGroup]="form
和 #formDirective="ngForm"
并不是一个好习惯。或者您可能更喜欢使用 @ViewChild
,并直接从您的 .ts 中执行此操作。其实问题不在于Angular,而在于Material。
如果您查看他们的 GitHub,您会看到:
/** Provider that defines how form controls behave with regards to displaying error messages. */
@Injectable({providedIn: 'root'})
export class ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
return !!(control && control.invalid && (control.touched || (form && form.submitted)));
}
}
表单将保持其 submitted
状态。所以你只需要删除函数的最后一部分。
这是我的解决方案(测试和工作)。我有一个材料模块,我已经实现了这个:
export class ShowOnInvalidTouchedErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl): boolean {
return !!(control && control.invalid && control.touched);
}
}
@NgModule({
providers: [
{
provide: ErrorStateMatcher, useClass: ShowOnInvalidTouchedErrorStateMatcher
}
],
exports: [
MatSnackBarModule,
MatTabsModule,
...
]
});
如果您只想在一种表单上使用此 ErrorStateMatcher,这是可能的。请参阅this Material example。这是同一个原理。
答案 4 :(得分:1)
添加属性-
@ViewChild(FormGroupDirective) formGroupDirective: FormGroupDirective;
并使用它代替this.myForm.reset();
this.formGroupDirective.resetForm();
这将重置错误显示并完成form.reset()的工作。但是表单以及字段仍将显示ng-invalid
类
查看此答案以获取更多详细信息-https://stackoverflow.com/a/56518781/9262627
答案 5 :(得分:0)
我也遇到同样的问题。我的问题是我正在使用mat-form-field
和formGroup
。重置表单submitted
后,标志未重置。
因此,对我有用的解决方案是将ngForm
的指令与formGroup
一起放入并传递onSubmit(form)
。添加
@ViewChild('form') form;
在组件中,然后我用
this.form.resetForm();
答案 6 :(得分:0)
我发现在调用resetForm()和reset()之后,提交的未重置并且保持为true,从而导致显示错误消息。这个解决方案对我有用。我在寻找在输入标签上调用select()和focus()的解决方案时找到了它,该标签也无法按预期工作。只需将您的行包装在setTimeout()中。有点hack,但是可以解决问题。
<form [formGroup]="myFormGroup" #myForm="ngForm">
…
<button mat-raised-button (click)="submitForm()">
</form>
submitForm() {
…
setTimeout(() => {
this.myForm.resetForm();
this.myFormGroup.reset();
}, 0);
}
答案 7 :(得分:0)
当尝试重置表单组中的特定表单控制器时,以下解决方案对我有用-
this.myForm.get('formCtrlName').reset();
this.myForm.get('formCtrlName').setValidators([Validators.required, Validators.maxLength(45), Validators.minLength(4), Validators.pattern(environment.USER_NAME_REGEX)]);
this.myForm.get('formCtrlName').updateValueAndValidity();
答案 8 :(得分:0)
没有什么能满足我的要求(Angular 7.2,Angular Material 7.3.7)。
尝试通过Submit方法在视图上传递事件:
<form [formGroup]="group" (ngSubmit)="onSubmit($event)">
<!-- your form here -->
</form>
然后使用它来重置currentTarget
和之后的表单:
public onSubmit(event): void {
// your code here
event.currentTarget.reset()
this.group.reset()
}
答案 9 :(得分:0)
简单的解决方法:将按钮与type="reset"
和功能submitForm()
一起使用
<form [formGroup]="MyForm" (ngSubmit)="submitForm()">
<input formControlName="Name">
<mat-error>
<span *ngIf="!tunersForm.get('Name').value && tunersForm.get('Name').touched"></span>
</mat-error>
<button type="reset" [disabled]="!MyForm.valid" (click)="submitForm()">Save</button>
</form>
答案 10 :(得分:0)
我对重置form指令没有运气。但是您也可以将输入状态更改为“待处理”。
this.myForm.get("email").reset();
this.myForm.get("password").reset();
答案 11 :(得分:0)
对于可能对此有帮助的任何人,我正在运行Angular 9.1.9,并且我不想仅重置表单的整体有效性来重置表单/控件,所以我只运行了
this.registerForm.setErrors(null);
...其中registerForm: FormGroup
会重置表格错误,导致:
this.registerForm.valid
...返回true
。
对于控件也可以这样做:
this.registerForm.get('email').setErrors(null)
触摸表单后,无论如何都会重新评估这些错误,因此,如果这还不够好,则当您要开始显示/隐藏错误UI时,可能需要使用布尔值标记来进一步精确定位。
在我的情况下,我不需要触摸指令。
答案 12 :(得分:0)
resetForm() {
this.myFormGroup.reset();
this.myFormGroup.controls.food.setErrors(null);
this.myFormGroup.updateValueAndValidity();
}
答案 13 :(得分:0)
form.reset()
在像Angular Material这样的自定义窗体控件上将不起作用,这就是该功能无法按预期工作的原因。
我的解决方法是这样的
this.form.reset();
for (let control in this.form.controls) {
this.form.controls[control].setErrors(null);
}
this.form.reset()
的问题是它将重置您的formcontrol值,但不会重置错误,因此您需要通过此代码行分别重置它们
for (let control in this.form.controls) {
this.form.controls[control].setErrors(null);
}
使用此方法,您无需使用FormGroupDirective
,这对我来说是一种更干净的解决方案。
答案 14 :(得分:-2)
将提交功能从表单移动到按钮,并向按钮添加类型:
<form [formGroup]="createForm">
<button (click)="submitForm()" type="submit">Submit</button>
<button (click)="createForm.reset()" type="reset">Reset</button>
</form>