我必须使用反应式表单做一个多步骤的大表单,我面临着一个性能问题,几乎所有表单中的字段都应该根据一些Dropdowns和单选按钮等的选择来显示隐藏条件。
为了便于理解这个问题,我在顶部添加了以下内容。Debug counter: {{counter}}
调用的方法是 getCondition()
在 multi-step-form.component.ts
并用于 multi-step-form.component.html
第43行。
我知道在*ngIf里面使用方法是不好的,但是我不知道如何解决这个问题。我需要在每次改变表单时检查显示条件。
我试着将这种情况复制到 叠加闪电战. 我正在使用像在例子中的一个复杂的数据模型。
我的问题是,在这种情况下,不使用模板中的方法来显示隐藏字段的最佳解决方案是什么?
下面你可以看到我目前的方法。
getDisplayCondition(field, i, value?: boolean) {
switch (field) {
case 'video': {
return this.masterForm[i].controls['resultMedia'].value === 'video';
}
case 'image': {
return this.masterForm[i].controls['resultMedia'].value === 'image';
}
case 'influence': {
return this.masterForm[i].controls['influence'].value === 'yes';
}
case 'radar': {
return this.radarList.length;
}
case 'innovationRadar': {
return this.masterForm[i].controls['isRadar'].value === 'yes';
}
case 'isMember': {
return value;
}
default: {
return true;
}
}
你有2个选择。
1 - 使用管道而不是函数,管道默认是纯函数,这意味着只有在数据变化时才会被调用,而不是在每次变化检测运行时。
@Pipe({name: 'displayField'})
export class DisplayFieldPipe implements PipeTransform {
transform(masterForm: form, i: number, value: boolean): boolean {
switch (field) {
case 'video': {
return this.masterForm[i].controls['resultMedia'].value === 'video';
}
case 'image': {
return this.masterForm[i].controls['resultMedia'].value === 'image';
}
case 'influence': {
return this.masterForm[i].controls['influence'].value === 'yes';
}
case 'radar': {
return this.radarList.length;
}
case 'innovationRadar': {
return this.masterForm[i].controls['isRadar'].value === 'yes';
}
case 'isMember': {
return value;
}
default: {
return true;
}
}
}
2 - 构建一个对象,包含你的字段是否应该被显示。你需要订阅表单valueChanges,并在每次重要的值发生变化时更新该对象。它基本上会调用你的getDisplayCondition,但它不会返回一个布尔值,而是会修改ngIfs中使用的对象。
这个对象会是这样的。
field = { field1: true, field2: false, ...};
而Html。
<input *ngIf="field.field1" id="field1">
你可以观察你的组件的变化。
this.form.valueChanges.subscribe(form => {...});
然后,在订阅里面,做你的logc 并设置布尔值到一个控制显示的变量, 然后,在*ngIf指令上使用它。 像这样:
this.form.valueChanges.subscribe(form => {
this.displaySomeField = form.field === "some-value";
});
<mat-form-field *ngIf="displaySomeField">
...
</mat-form-field>