如何在Angular 5中仅在所有子元素完全加载后显示页面?

3

我有一个页面,其中包含几个子组件:

<div class="wrapper" *ngIf="isPageFullyLoaded">

  <header></header>

  <main class="content">
      <trip-list></trip-list> 
  </main>

  <footer></footer>
 </div>

ts文件包含以下内容:
...
public isPageFullyLoaded = false;
...
ngAfterContentInit() {
        this.isPageFullyLoaded = true;
    }

The child trips-list:
<section *ngIf="trips">
    <ul>
        <li *ngFor="let data of trips" >
...

旅行列表是使用rest api加载的:
getTrips() {
    this.fundService.getTrips().subscribe(
      data => { this.trips= data; }, 
      err => console.error(err),
      () => console.log(this.trips)
    );
  }

我还尝试了ngAfterViewInit

我需要一种方法,在子组件完全加载后才显示主div。因为如果在div中使用*ngIf,子组件就不会被加载。

有什么好的想法吗?


1
你有办法知道子元素是否已经加载? - ConnorsFan
ngAfterViewChecked() 中使用一些布尔值。 - Shashank Vivek
ngAfterViewChecked是个好主意,但是在模板中如何使用布尔值呢? - user2304483
@user2304483 将您的组件内容包装在一个 div 中,并使用 *ngIf - Ploppy
我已经尝试过这个,我看到的是页脚和页眉先加载,然后才是其他子元素。我需要在所有内容都加载完成后再显示页面。 - user2304483
1个回答

1
如果属性allChildrenLoaded表示子元素已加载,您可以将其绑定到主div的hidden属性。与ngIf相反,它仅在满足条件时加载元素,hidden属性隐藏实际存在于DOM中的元素。
<div class="wrapper" [hidden]="!allChildrenLoaded">
  <child1></child1>
  <child2 *ngFor="let value of values"></child2>
  <trip-list (loaded)="onTripListLoaded()"></trip-list>
</div>

你可以使用@ViewChildrenQueryListchanges事件来检测组件何时被加载:
export class ParentComponent implements AfterViewInit {

  @ViewChildren(Child1Component) children1: QueryList<Child1Component>;
  @ViewChildren(Child2Component) children2: QueryList<Child2Component>;

  private child1Loaded = false;
  private children2Loaded = false;
  private tripListLoaded = false;

  private expectedChildren2Count = 5; // Expected number of Child2Component to be loaded

  constructor(private cd: ChangeDetectorRef) { }

  ngAfterViewInit() {
    this.child1Loaded = this.children1.length > 0;
    this.children2Loaded = this.children2.length === expectedChildren2Count;
    this.cd.detectChanges(); // To avoid possible runtime error

    this.children1.changes.subscribe(() => {
      this.child1Loaded = this.children1.length > 0;
    });
    this.children2.changes.subscribe(() => {
      this.children2Loaded = this.children2.length === expectedChildren2Count;
    });
  }

  onTripListLoaded() {
    this.tripListLoaded = true;
  }

  get allChildrenLoaded(): boolean {
    return this.child1Loaded && this.child2Loaded && this.tripListLoaded;
  }
}

trip-list组件中,当内容加载完成时,可以发出loaded事件。父组件使用事件绑定来处理该事件(请参见上面的标记)。
@Output() public loaded: EventEmitter<any> = new EventEmitter();

getTrips() {
    this.fundService.getTrips().subscribe(
      data => { 
        this.trips= data; 
        this.loaded.emit();
      }, 
      err => console.error(err),
      () => console.log(this.trips)
    );
  }

查看此演示,请访问 this stackblitz

1
你检查了 this.children1.length > 0,但是如果我们有可重复的子组件,例如三个相同的组件,它们具有不同的加载时间呢?看起来当任何一个组件被渲染时,这个检查将变为 true,但并非所有组件都是如此。 - P.S.
如果您知道应该加载多少个,可以这样做:this.children1Loaded = this.children1.length === expectedChild1Count; - ConnorsFan
@CommercialSuicide - 我更新了答案以考虑到那种情况。感谢您的评论! - ConnorsFan
我将trip-list子项添加到原始问题中。 - user2304483
我更新了答案以考虑到 trip-list 组件。 - ConnorsFan
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接