2017-07-04 65 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

相關問題