I've got a user profile form with multiple steps, i.e. a wizard. On Submit/Save, the entire user profile form has to be submitted to an API I'm using NGXS and NGXS Forms.
At the moment I have implemented the UI as a single Angular Reactive Forms and a single state property form
, the model is of the type the API expects. There is a component for each step, but they all use the same form
.
The big problem with this approach is that I can't detect whether the fields on a step are valid or not, I can only detect if the entire form is valid.
To solve this, I think I have to create multiple Angular forms. However, I can't bind them all to the same state property form
, as on each step I only have a subset of properties.
So, my thinking now is to create a form property in my state for each step, each with its own interface for the properties it stores. Then, I can create a selector that will return the entire object I can submit to the API.
In code, currently:
form: {
model: UserProfileDto,
....
}
Proposal:
personalDetailsForm: {
model: PersonalDetailsModel,
},
workDetailsForm: {
model: WorkDetailsModel
}
@Selector(ProfileDetails)
profileDetails(state: ProfileState) {
return {...state.workDetailsForm.model, ...state.personalDetailsForm.model}
}
Is this the way to go or is there an easier approach?
It's very opinion question, but I can share my thoughts.
In parent component I will create separate form for every step:
export class Component {
ngOnInit(): void {
this.workDetailsForm = this.buildWorkForm();
this.personalDetailsForm = this.buildPersonalForm();
// and through merge + valueChanges you can get the last object at any time
merge(
this.workDetailsForm.valueChanges,
this.personalDetailsForm.valuesChanges
)
.subscribe(() => {
this.profileDetails = {
...this.workDetailsForm.value,
...this.personalDetailsForm.value
};
});
// here you can check, that the whole form is valid
merge(
this.workDetailsForm.statusChanges,
this.personalDetailsForm.statusChanges
)
.subscribe(() => {
this.isFormValid = this.workDetailsForm.valid && this.personalDetailsForm.valid;
});
}
}
<app-step-work-details
[form]="workDetailsForm"> </app-step-work-details>
<app-step-personal-details
[form]="personalDetailsForm"> </app-step-personal-details>