Angular - テンプレートをロードする前にデータを受信するまで待つ。

そこで、このテンプレートで、複数のコンポーネントを動的にレンダリングするコンポーネントを持っています

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

つまり、データを入手したら、コンポーネントが購読しているサービスObservableをトリガーして、収集したデータを処理するのです。

**PROBLEM:***

**APIコールがすべてのコンポーネントのロード前に行われた場合、私はこれらのサービスメソッドをトリガーしてデータを渡しますが、誰もこれらのObservablesを購読することはありません。

というアプローチが考えられます:

まずデータを読み込み、データを読み込んでからテンプレートをレンダリングし、その結果、これらのコンポーネントをすべて動的にレンダリングし、そのときに初めてこれらのサービスメソッド(Observables)をトリガーします。

各コンポーネントのAPIコールを作りたくはありません:

// 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をレンダリングする前に待つにはどうすればよいでしょうか。

質問が少し長くなってしまいましたが、もし詳細が必要であれば教えてください。

ありがとうございます!

質問へのコメント (13)
ソリューション

人々がくれたさまざまなアプローチを研究した結果、私は async パイプで解決策を見つけました。しかし、それを実装する方法を理解するのに時間がかかりました。

**解決策:***。

// Declaring the Promise, yes! Promise!
filtersLoaded: Promise;

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

テンプレートでは、ObservableまたはPromiseを必要とするasyncパイプを使用します。

<div *ngIf="filtersLoaded | async">
    <div [saJquiAccordion]="{active: group.value['collapsed']}" *ngFor="let group of filterGroupsTemplate | keysCheckDisplay;">
        <div>
            <h4>{{group.key | i18n}}</h4>





        </div>
    </div>
</div>

NOTE:

  • asyncパイプは、私が理解したところでは、ObservableまたはPromise`を必要とします。
  • resolverはAngularのルーティングでコンポーネントに到達したときに使用されるため、私はこのアプローチを使用しませんでした。このコンポーネントはより大きなコンポーネントの一部であり、他の通常のコンポーネントのようにルーティングを通してインスタンス化されるわけではありません。(その方法を試しましたが、少し作業しただけで仕事になりませんでした)
解説 (3)

ルートがアクティブになる前にデータがロードされている(またはフィルターが初期化されている)ことを確認するために resolver を使用することができます。

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

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

解説 (7)