2017-07-04 32 views
5

所以,我有一个动态呈现几部分组成,与此模板组件:角 - 等待,直到我装模板之前接收数据

<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> 

的事情是,需要的数据来填充这些组件我是从一个API调用得到它:

 this.getFiltersSubscription = this.getFilters().subscribe(
      (filters) => { 
       this.filters = filters; 
       log.info('API CALL. getting filters'); 

       // Sending data to fieldform components 
       this.iboService.updateIBOsRankList(filters['iboRank'].data); 
       this.iboService.updateIBOsNewsletterOptions(filters['iboNewsletter'].data); 
       this.iboService.updateIBOsTotalOrders(filters['iboTotalOrders'].data); 
      } 
     ); 

所以,一旦我有我的数据,我触发服务可观察这我部件SUBSCR与相似,然后他们将处理收集的数据。

问题:

如果API调用的所有组件加载之前提出的,我会触发这些服务方式传递数据,但没有人会被订阅的观测量。

的方法是:

加载数据第一,只有当我有加载的数据,我会呈现模板,因此,动态地呈现所有这些组件,然后才我会触发这些服务方法(Observables)。

我不想让API调用的每个组件,因为它可以像60级的部件,我会相当松散的抽象FO代码,但我preffer做这样的事情:

// 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); // HERE I'M PASSING DATA TO THE COMPONENT RENDERED DYNAMICALY. BUT IF this.filters IS UNDEFINED, IT BREAKS 
       } 
      } 
     ); 

为了做到这一点,我需要确保this.filters定义,因此,我得出的结论是:

我怎么能等到API调用结束,this.filters被渲染我的HTML模板之前定义的?

对不起,如果我的问题有点长,如果你需要更多的细节只是让我知道。

谢谢!

+0

请尝试我在异步管https://angular.io/api/common/AsyncPipe – Gary

+0

@Gary看看。但是,你可以发表一个例子吗?例如,我在'ngFor'中多次使用'async'管道。但是我从来没有使用异步管道,但没有呈现可观察的。我没有渲染'过滤器'也没有*打印*它,我只需要等到它被定义为加载整个模板。 – SrAxi

+0

难道你不能只是添加一个'* ngIf = filters'来阻止模板渲染,直到'filters'被填充? – Saravana

回答

4

学习的人给了我不同的方法后,我发现了async管的解决方案。但是,我花了一段时间才了解如何实施它。

解决方案:

// 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); 
       } 
      } 
     ); 

在模板中,我用的是async管道将需要一个ObservablePromise

<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> 

注:

  • async管需要一个Observable或者从我的理解一个Promise,这就是为什么只有这样,才能使工作是由因为当你通过角的到达组件它是用来创建一个Promise
  • 我没有使用resolver方法路由。该组件是较大组件的一部分,并不像其他任何常规组件那样通过路由实例化。 (尝试这种做法虽然工作有点用吧,没做的工作)
+1

非常感谢,这解决了我的问题! – Inigo

3

您可以使用resolver确保在路由激活之前加载这些数据(或者您的过滤器已经初始化)。

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

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

+0

在所有的例子和文档中,我发现这在导航传递一个id作为参数时有效。它是否在*标准*组件中起作用?如果是这样,你能举一个例子吗?谢谢! – SrAxi

+0

是的,使用具有ID的解析器就是典型的例子,但这取决于你如何处理它。在initIBOsFilters $''初始化过滤器后,只需定义一个解析器并从实现的解析函数返回。 – Matt

+0

我正在研究它。因为我没有找到一个合适的解决方案'async' pipe,我正在研究'resolver'示例和文档。你说我可以等到'initIBOsFilters $'完成,然后渲染我的组件?问题是每个过滤器组件*(它是一个带有很多过滤器的动态表单)将触发'initIBOsFilters $',所以我实际上不知道什么时候所有加载的组件动态完成加载。有小费吗?例子? – SrAxi

相关问题