Angular - Wait until I receive data before loading template

前端 未结 3 993
野的像风
野的像风 2020-12-23 17:20

So, I have a component that renders several components dynamically, with this template:

相关标签:
3条回答
  • 2020-12-23 17:23

    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)
    0 讨论(0)
  • 2020-12-23 17:27

    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

    0 讨论(0)
  • 2020-12-23 17:34
    <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);
        });
      }
    }
    
    0 讨论(0)
提交回复
热议问题