Angular - 等到收到数据后再加载模板

问题描述 投票:0回答:6
angular typescript
6个回答
74
投票

研究了人们给我的不同方法后,我在

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

注意:

    根据我的理解,
  • async
    管道需要一个
    Observable
    Promise
    ,这就是为什么让它工作的唯一方法是创建一个
    Promise
  • 我没有使用
    resolver
    方法,因为当你通过 Angular 的路由到达组件时会使用它。该组件是一个更大组件的一部分,它不像任何其他普通组件那样通过路由进行实例化。 (尽管尝试了这种方法,做了一些工作,但没有成功)

19
投票

您可以使用

resolver
确保在激活路线之前加载这些数据(或您的过滤器已初始化)。

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

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


12
投票
<p class="p-large">{{homeData?.meta[0].site_desc}}</p>

刚刚使用了一个“?”在从服务器加载数据的变量之后。

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

1
投票

替代

async
可以创建变量
isLoading = true
。虽然它确实显示由 Angular 提供的微调器,而不是使用 *ngIf 提供的内容。当您的订阅触发时,分配
isLoading = false
。 这样您就不会收到任何有关丢失数据的错误,因为从技术上讲,使用它的内容尚不存在。


0
投票

我知道这对聚会来说已经很晚了,但对我有用的是在我的减速器中添加一个加载布尔值到我的状态。

减速器.ts:

export interface State {
 things: Stuff;
 loaded: boolean;
}
export const reducers: ActionReducerMap<State> = {
    things: reducer,
    loaded: loadedReducer,
};

然后确保导出加载的函数,以便在状态恢复时切换为 true

export function loadedReducer(state: boolean = false, action: ThingActions): boolean {
    switch (action.type) {
        case ThingActionTypes.GetThings:
            return true;
    }
    return state;
}

然后在你的 ts 中订阅已加载的内容。

父组件.ts:

this.loaded$ = this.store.pipe(select(fromReducer.loaded));

并在模板中像异步管道一样使用它。

parent.component.html:

        <ng-container *ngIf="(loaded$ | async); else loading">
            <child-component></child-component>
        </ng-container>
        <ng-template #loading></ng-template>

0
投票

编辑:这不是正确的也不是最好的方法,但是:

最简单的解决方案是将其包装在 ngIf 中,我认为这不是一个好的做法,但它解决了问题。

在这种情况下错误是:

未定义的标题

标记:

<div *ngIf="form">
    {{form.Title}}
</div>
© www.soinside.com 2019 - 2024. All rights reserved.