Reputation: 15
I have to do a multi-step big form using reactive forms, and I'm facing an issue with the performance. Almost all the fields from the form should have show/ hide condition based on the selections from some Dropdowns, radio buttons etc.
To be easy to understand the issue I added on the top Debug counter: {{counter}}
Method called is getCondition()
in multi-step-form.component.ts
and used in multi-step-form.component.html
line 43.
I know is not good to use methods inside of the *ngIf but I don't have any idea how to fix this issue. I need to check the display condition at each change of the form.
I tried to replicate this situation in Stackblitz. I'm using like in the example a complex data model.
My question is, which is the best solution for this case to show/ hide the fields without using the method in the template?
Below you can see my current method.
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;
}
}
Upvotes: 0
Views: 3229
Reputation: 1793
You have 2 choices:
1 - Use a pipe instead of a function, a pipe is pure by default which means its going to be called only when the data change and not at every change detection run.
@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 - Build an object that contains whether or not your fields should be displayed. You would need to subscribe to the form valueChanges and update the object everytime one of the important value changes. It would basically call your getDisplayCondition but instead of returning a boolean it would modify the object that is being used in the ngIfs
The object would look like:
field = { field1: true, field2: false, ...};
And the Html:
<input *ngIf="field.field1" id="field1">
Upvotes: 1
Reputation: 41
You can observe the changes in your component:
this.form.valueChanges.subscribe(form => {...});
And then, inside the subscribe, do your logc and set the boolean value to a variable that controls the display, and then, use it on the *ngIf directive. Like this:
this.form.valueChanges.subscribe(form => {
this.displaySomeField = form.field === "some-value";
});
<mat-form-field *ngIf="displaySomeField">
...
</mat-form-field>
Upvotes: 2