Angular - Wait Until I Receive Data Before Loading Template


Answer :

After studying the different approaches that people gave me, I found the solution on the async pipe. But, it took me a while to understand how to implement it.

Solution:

// Declaring the Promise, yes! Promise! filtersLoaded: Promise<boolean>;  // Later in the Component, where I gather the data, I set the resolve() of the Promise this.getFiltersSubscription = this.getFilters().subscribe(     (filters) => {         this.filters = filters;         log.info('API CALL. getting filters');          this.filtersLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data     } );  // In this listener triggered by the dynamic components when instanced, // I pass the data, knowing that is defined because of the template change  // Listens to field's init and creates the fieldset triggering a service call // that will be listened by the field component this.iboService.initIBOsFilters$.subscribe(     (fieldName) => {         if (fieldName === 'IBOsRankSelectorFieldComponent') {             log.data('inside initIBOsFilters$ subscription, calling updateIBOsFilters()', fieldName);             this.iboService.updateIBOsRankList(this.filters['iboRank'].data);         }     } ); 

In the template, I use the async pipe that needs an Observable or a Promise

<div *ngIf="filtersLoaded | async">     <div [saJquiAccordion]="{active: group.value['collapsed']}" *ngFor="let group of filterGroupsTemplate | keysCheckDisplay;">         <div>             <h4>{{group.key | i18n}}</h4>             <form id="ibo-{{group.key}}" class="form-horizontal" autocomplete="off" style="overflow: initial">                 <fieldset *ngFor="let field of group.value | keys">                     <ng-container *ngComponentOutlet="fieldSets[field.value.template];                                     ngModuleFactory: smartadminFormsModule;"></ng-container>                 </fieldset>             </form>         </div>     </div> </div> 

NOTE:

  • async pipe need an Observable or a Promise from what I understood, that's why the only way to make it work was by creating a Promise
  • I didn't use the resolver approach because it's used when you arrive to the component through Angular's routing. This component is part of a larger component and it's not instanced through routing like any other normal component. (Tried that approach though, worked a bit with it, didn't do the job)

You could use a resolver to ensure those data are loaded (or your filters have been initialized) before the route is activated.

https://blog.thoughtram.io/angular/2016/10/10/resolving-route-data-in-angular-2.html

https://angular.io/api/router/Resolve


<p class="p-large">{{homeData?.meta[0].site_desc}}</p> 

Just Used a "?" after the variable that has been getting loaded with data from the server.

home.component.ts

import { Component, OnInit } from '@angular/core'; import { HomeService } from '../services/home.service';  @Component({   selector: 'app-home',   templateUrl: './home.component.html',   styleUrls: ['./home.component.scss'] }) export class HomeComponent implements OnInit {   public homeData: any;   constructor(private homeService: HomeService) {}    ngOnInit(): void {     this.homeService.getHomeData().subscribe( data => {       this.homeData = data[0];     }, error => {       console.log(error);     });   } } 

Comments

Popular posts from this blog

Converting A String To Int In Groovy

"Cannot Create Cache Directory /home//.composer/cache/repo/https---packagist.org/, Or Directory Is Not Writable. Proceeding Without Cache"

Android How Can I Convert A String To A Editable