ngIf conditional template
An easy way to wait for data to load before rendering is to add an *ngIf directive to the block that needs to wait for the data.
<div *ngIf="data">My data</div>
data: any;
ngOnInit() {
this.apiService.getData$().subscribe((results) => {
data = results;
});
}
This approach is straightforward but experienced developers might recommend using an async pipe. Let’s do that
ngIf conditional template with async pipe
<div *ngIf="data | async">My data</div>
data$: Observable<any>;
ngOnInit() {
this.data = this.apiService.getData$();
}
This solution is more elegant but the data variable must be an observable.
In a nutshell those solutions are the way to go when a part of the template depends on a condition. Actually if the whole component’s template depends on a condition, we can wrap the entire template inside a conditional block.
<ng-container *ngIf="data">
<!-- whole component template here -->
</ng-container>
Route resolver
A resolver is another way to load data, the data loading is done by the angular router before rendering the component. This approach is very convenient within the component’s code, as it eliminates the need to wait for data and allows direct access to it during the ngOnInit lifecycle.
@NgModule({
imports: [
RouterModule.forRoot([
{
path: 'my-component',
component: MyComponent,
resolve: {
data: MyComponentResolver
}
}
])
],
exports: [RouterModule]
})
export class AppRoutingModule {}
@Injectable({ providedIn: 'root' })
export class MyComponentResolver implements Resolve<any> {
constructor(private apIService: ApiService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> {
return this.apiService.getData$();
}
}
The data is stored in the activatedRoute.snapshot.data.
constructor(private activatedRoute: ActivatedRoute) {}
ngOnInit() {
console.log(this.activatedRoute.snapshot.data);
}