My problem scenario is as follows,
I have a page with a large form (+100 inputs). These inputs are divided into sections and those sections are developed as different components (for reusing purposes). So the general layout of the page is something like this,
<div>
<form-section-a></form-section-a>
<form-section-b></form-section-b>
<form-section-c></form-section-c>
...
<form-section-z></form-section-z>
</div>
Each form section will take some time to process because most of the inputs are material select boxes, and necessary data need to be loaded from the REST API and processed.
In the above shown layout, angular will try to render all form sections at once, hence adding up processing times of each section, which will cause the browser to freeze.
So, my plan is to load sections one after the other. Is there any recommended way to achieve this?
I have tried to write a structural directive to load components one after the other. Even though the directive works, there is no way I can know when the component has finished its internal processing work (May be the AfterViewInit hook). The directive looks something like this,
<div tcSequentialRenderer>
<form-section-a *tcIfPreviousBlockLoaded></form-section-a>
<form-section-b *tcIfPreviousBlockLoaded></form-section-b>
<form-section-c *tcIfPreviousBlockLoaded></form-section-c>
...
<form-section-z *tcIfPreviousBlockLoaded></form-section-z>
</div>
.
@Directive({selector: '[tcSequentialRenderer]'})
export class SequentialRendererDirective implements AfterViewInit {
@ContentChildren(IfPreviousBlockLoadedDirective) directives: QueryList<IfPreviousBlockLoadedDirective>;
ngAfterViewInit() {
// start from first item
if (this.directives.length > 0) {
this.directives.toArray()[0].show();
}
let directivesArray = this.directives.toArray();
for (let i = 1; i < directivesArray.length; i++) {
directivesArray[i - 1].done.subscribe(status => {
if (status) {
directivesArray[i].show();
}
});
}
}
}
.
@Directive({selector: '[tcIfPreviousBlockLoaded]'})
export class IfPreviousBlockLoadedDirective {
private isShown = false;
public done: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(
private tplref: TemplateRef<any>,
private vcref: ViewContainerRef
) { }
public show(): void {
if (!this.isShown) {
this.vcref.createEmbeddedView(this.tplref);
this.isShown = true;
}
}
}
If I can somehow access the associated component from the IfPreviousBlockLoadedDirective
this method will work seamlessly.
Are there any suggestions to fix this, or are there any other ways to achieve this without changing the form-section components?
NOTE: Form sections can be any angular component.