We have implemented a wizard functionality with lazy loading, consisting of a parent component and multiple child components.
const routes: Routes = [
{
path : '',
component : WizardHomeComponent,
canActivate: [HomeGuard],
children : [
{
path : 'route1',
component : C1Component,
canActivate: [ChildGuard]
},
{
path : 'route2',
component : C2Component,
canActivate: [ChildGuard]
},
{
path : 'route3',
component : C3Component,
canActivate: [ChildGuard]
}
{
path : 'complete',
component : CompleteFlowComponent,
canActivate: [ChildGuard]
}
]
}
];
The HomeGuard
utilizes a service that makes an API call if no data is present. The value is then set in the service's Behaviour Subject
to resolve the guard.
HomeGuard
return new Observable(observer=> {
this.apiService.getAPIResult().subscribe(res=>{
this.subjectService.setRequestData(res)
observer.next(true)
});
})
Below is the code for the subject service:
Subject Service
private requestDataSource : BehaviorSubject<IWizard[]> = new BehaviorSubject<IWizard[]>(null);
public _requestData: Observable<IWizard[]> = this.requestDataSource.asObservable();
get requestData() {
return this._requestData;
}
setRequestData(state) {
this.requestDataSource.next(state);
}
Furthermore, there is a child route guard called ChildGuard. This guard subscribes to the behaviour subject, checks for conditions, and allows entry to the child component based on the result.
ChildGuard
return this.subjectService.requestData
.pipe(
tap(wizard => {
activeStep = wizard.filter(x=>x.isActive == true);
/* Additional logic for conditions */
})
)
.pipe(
map(wizard => isAllowed)
)
Within the child route components, the isActive attribute is updated as users navigate. However, an issue arises when users hit the browser back button, as the values are not set in the behavior subject prior to entry into the child component.
An attempted solution involves subscribing to the requestData observable within the WizardHomeComponent, modifying the data, and setting the subject again. However, this results in an infinite loop.
WizardHomeComponent
this.subjectService.requestData.subscribe(res=>{
/* Code to edit the res */
const modifiedData = this.modificationFunction(res);
this.subjectService.setRequestData(modifiedData)
});