我有一个组件,可以动态呈现多个组件,使用以下模板:

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

所以,一旦我有了数据,我就会触发一个服务,我的组件订阅了这个服务,然后它们就会处理收集到的数据.

PROBLEM

如果API调用是在所有组件加载之前进行的,我将触发这些传递数据的服务方法,但没有人订阅这些可观察的服务.

一种方法是:

首先加载数据,只有当我加载了数据时,我才会呈现模板,因此,动态呈现所有这些组件,然后我才会触发这些服务方法(可观察的).

我不想对每个组件进行API调用,因为它可以是60个组件,我会对代码进行松散的抽象,但我更喜欢这样做:

// 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,因此,我得出结论:

在呈现模板html之前,如何等待API调用结束并定义this.filters

对不起,如果我的问题有点长,如果你需要更多的细节,请告诉我.

谢谢

推荐答案

在研究了人们给我的不同方法后,我在async号管道上找到了解决方案.但是,我花了一段时间才明白如何实施它.

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

在模板中,我使用了需要ObservablePromiseasync管道

<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管道需要ObservablePromise,这就是为什么唯一能让它工作的方法是创建Promise
  • 我没有使用resolver方法,因为它是在通过Angular的路由到达组件时使用的.该组件是较大组件的一部分,不像其他普通组件那样通过布线实例化.(Tried that approach though, worked a bit with it, didn't do the job)

Typescript相关问答推荐

类型脚本:类型是通用的,只能索引以供阅读.(2862)"

如何传递基于TypScript中可变类型的类型?

TypScript ' NoInfer '类型未按预期工作

Angular 17 Select 错误core.mjs:6531错误错误:NG 05105:发现意外合成监听器@transformPanel.done

需要使用相同组件重新加载路由变更数据—React TSX

为什么typescript要把这个空合并转换成三元?

类型脚本泛型最初推断然后设置

如何使用函数填充对象?

无法从Chrome清除还原的初始状态数据

为什么在回调函数的参数中不使用类型保护?

react 路由Use RouteLoaderData类型脚本错误

具有自引用属性的接口

保护函数调用,以便深度嵌套的对象具有必须与同级属性函数cargument的类型匹配的键

无法将从服务器接收的JSON对象转换为所需的类型,因此可以分析数据

我在Angular 17中的environment.ts文件中得到了一个属性端点错误

有没有办法在Zod中使用跨字段验证来判断其他字段,然后呈现条件

ANGLE NumberValueAccessor表单控件值更改订阅两次

Angular 16将独立组件作为对话框加载,而不进行布线或预加载

类型脚本中参数为`T`和`t|unfined`的重载函数

TypeScript:如何使用泛型和子类型创建泛型默认函数?