Angular Material Stepper 导致 mat-form 字段在返回到旧步骤时验证动态表单
Angular Material Stepper causes mat-formfield to validate for dynamic forms when returning to an older step
使用动态表单时 angular materials mat-stepper
出现问题。例如,我有一个包含 3 个步骤的步进器,每个步骤都有自己的形式。然而,第一步使用隐藏表单来确定它是否有效,因为这一步可以动态添加更多表单,因此不可能将所有表单绑定到该步骤。
当您处于第一步时,您可以创建多个表单,并且一切都按预期工作,而不会对添加的新表单进行任何随机验证。如果您转到第 2 步或第 3 步并返回到第一步,然后创建一个新表单,它将自动开始并以红色突出显示所有字段。
我尝试了很多不同的尝试来压制但是我没有成功。下面是一个基本示例,说明我的第一步如何包含绑定到步骤控件的 hiddenForm、默认表单和用于在该步骤中创建更多表单的按钮。
我对尝试解决此问题的研究使我相信 material 步进器会使所有 mat-form-fields 在无效时变为红色,无论是否新添加。
<mat-horizontal-stepper [linear]="true">
<mat-step [stepControl]="hiddenForm" label="step 1"
<form [formGroup]="myForm">
<mat-form-field>
<mat-label>
First Name
</mat-label>
<input [formControl]="firstName"matInput>
<mat-error *ngIf="!firstName.valid && firstName.touched">
First Name required
</mat-error>
</mat-form-field>
</form>
<button (click)="AddNewForm()">Add New Form</button>
</mat-step>
</mat-horizontal-stepper>
尝试失败次数:(当前表格为新增表格)
this.currentForm.markAsUntouched();
this.currentForm.markAsPristine();
this.currentForm.setErrors(null);
this.currentForm.reset();
this.currentForm.get('firstName).setErrors(null);
this.currentForm.get('firstName).reset();
this.currentForm.get('firstName).markAsPristine();
this.currentForm.get('firstName).markAsUntouched();
<mat-step [completed]="true" ..> ( on all steps )
背景资料
我找到的最好的解决方案是更改 mat-stepper
上的参数。在任何给定时间都选择了一个步骤。在步骤上,您可以更改步骤是否已与之交互。如果之前访问过某个步骤,则 interacted
参数将设置为 true。由于这是有意且有意义的,因此将 class 添加到所有 mat-form-fields
导致它们变红会导致问题。
这会导致糟糕的用户体验的场景:
您完成第一步,进入第二步。进入第二步后,您意识到自己在第一步中犯了错误,并决定返回到第一步。您进行更改,然后再次进行第二步。因为如果您有 mat-form-fields
,您已经访问过此步骤,将添加 class(可能还有其他更改)并且您的表单字段现在全部为红色。这是一个糟糕的用户体验,因为用户在技术上没有犯任何错误并且可以承受。
第一步是创建动态表单。为简单起见,让我们使用英雄之旅类比。在我们的第一步中,您可以动态添加表单。每种形式代表您要添加的新英雄。您已经添加了 3 个英雄并继续进行第 2 步。在完成第 2 步之前,您意识到您忘记了一些英雄并继续回到第 1 步。现在当您单击我们的按钮 'create hero' 时,您的动态表单会弹出,但您所有的 mat-form-fields
现在是红色的,就像用户犯了错误一样。这是另一个糟糕的用户体验。
修复:
hero.stepper.html
<mat-horizontal-stepper [linear]="true"
(selectionChange)="stepChanged($event, stepper);">
<mat-step [stepControl]="hiddenForm" label="step 1"
<form [formGroup]="heroFormGroupArray[0]">
<mat-form-field>
<mat-label>Hero Name</mat-label>
<input [formControl]="heroName"matInput>
...
</mat-form-field>
</form>
<button (click)="AddNewHero()">Add New Hero</button>
</mat-step>
</mat-horizontal-stepper>
hero.stepper.ts
export class heroStepComponent implements OnInit {
constructor(){
...
}
ngOnInit(){
...
}
stepChanged(event, stepper){
stepper.selected.interacted = false;
}
}
根据之前的 ,我发现了 stepChanged 函数的更好实现:
stepChanged(event: StepperSelectionEvent) {
if (event.previouslySelectedIndex > event.selectedIndex) {
event.previouslySelectedStep.interacted = false;
}
}
此代码将仅在您转到之前步骤的步骤上设置交互 属性。
使用动态表单时 angular materials mat-stepper
出现问题。例如,我有一个包含 3 个步骤的步进器,每个步骤都有自己的形式。然而,第一步使用隐藏表单来确定它是否有效,因为这一步可以动态添加更多表单,因此不可能将所有表单绑定到该步骤。
当您处于第一步时,您可以创建多个表单,并且一切都按预期工作,而不会对添加的新表单进行任何随机验证。如果您转到第 2 步或第 3 步并返回到第一步,然后创建一个新表单,它将自动开始并以红色突出显示所有字段。
我尝试了很多不同的尝试来压制但是我没有成功。下面是一个基本示例,说明我的第一步如何包含绑定到步骤控件的 hiddenForm、默认表单和用于在该步骤中创建更多表单的按钮。
我对尝试解决此问题的研究使我相信 material 步进器会使所有 mat-form-fields 在无效时变为红色,无论是否新添加。
<mat-horizontal-stepper [linear]="true">
<mat-step [stepControl]="hiddenForm" label="step 1"
<form [formGroup]="myForm">
<mat-form-field>
<mat-label>
First Name
</mat-label>
<input [formControl]="firstName"matInput>
<mat-error *ngIf="!firstName.valid && firstName.touched">
First Name required
</mat-error>
</mat-form-field>
</form>
<button (click)="AddNewForm()">Add New Form</button>
</mat-step>
</mat-horizontal-stepper>
尝试失败次数:(当前表格为新增表格)
this.currentForm.markAsUntouched();
this.currentForm.markAsPristine();
this.currentForm.setErrors(null);
this.currentForm.reset();
this.currentForm.get('firstName).setErrors(null);
this.currentForm.get('firstName).reset();
this.currentForm.get('firstName).markAsPristine();
this.currentForm.get('firstName).markAsUntouched();
<mat-step [completed]="true" ..> ( on all steps )
背景资料
我找到的最好的解决方案是更改 mat-stepper
上的参数。在任何给定时间都选择了一个步骤。在步骤上,您可以更改步骤是否已与之交互。如果之前访问过某个步骤,则 interacted
参数将设置为 true。由于这是有意且有意义的,因此将 class 添加到所有 mat-form-fields
导致它们变红会导致问题。
这会导致糟糕的用户体验的场景:
您完成第一步,进入第二步。进入第二步后,您意识到自己在第一步中犯了错误,并决定返回到第一步。您进行更改,然后再次进行第二步。因为如果您有
mat-form-fields
,您已经访问过此步骤,将添加 class(可能还有其他更改)并且您的表单字段现在全部为红色。这是一个糟糕的用户体验,因为用户在技术上没有犯任何错误并且可以承受。第一步是创建动态表单。为简单起见,让我们使用英雄之旅类比。在我们的第一步中,您可以动态添加表单。每种形式代表您要添加的新英雄。您已经添加了 3 个英雄并继续进行第 2 步。在完成第 2 步之前,您意识到您忘记了一些英雄并继续回到第 1 步。现在当您单击我们的按钮 'create hero' 时,您的动态表单会弹出,但您所有的
mat-form-fields
现在是红色的,就像用户犯了错误一样。这是另一个糟糕的用户体验。
修复:
hero.stepper.html
<mat-horizontal-stepper [linear]="true"
(selectionChange)="stepChanged($event, stepper);">
<mat-step [stepControl]="hiddenForm" label="step 1"
<form [formGroup]="heroFormGroupArray[0]">
<mat-form-field>
<mat-label>Hero Name</mat-label>
<input [formControl]="heroName"matInput>
...
</mat-form-field>
</form>
<button (click)="AddNewHero()">Add New Hero</button>
</mat-step>
</mat-horizontal-stepper>
hero.stepper.ts
export class heroStepComponent implements OnInit {
constructor(){
...
}
ngOnInit(){
...
}
stepChanged(event, stepper){
stepper.selected.interacted = false;
}
}
根据之前的
stepChanged(event: StepperSelectionEvent) {
if (event.previouslySelectedIndex > event.selectedIndex) {
event.previouslySelectedStep.interacted = false;
}
}
此代码将仅在您转到之前步骤的步骤上设置交互 属性。