Angular Lifecycle Hook - 构造函数初始化的数据在视图init之后加载

时间:2018-03-05 12:35:57

标签: angular typescript firebase google-cloud-firestore lifecycle

我已经加载了一个firestore文档并将其转换为组件构造函数中的普通js对象,然后在模板中访问了对象的字段值,这意味着它们需要花费一秒钟来加载。因此,即使do渲染到DOM,我在浏览器控制台中也会遇到以下类型的错误(此处访问{{invoice.id}}时:

  

无法读取未定义

的属性'id'

根据我的理解,构造函数中定义的任何内容都应该在视图初始化时立即可用,那么为什么会出现这种情况/我该如何防止这种情况呢?

查看-invoice.component.html:

<h4 class="page-title">Invoice Summary</h4>

<p>ID: {{ invoice.invoiceId }}</p>
<p>Reference: {{ invoice.reference }}</p>
<p>Date: {{ invoice.date | date: 'dd/MM/yyyy' }}</p>

查看-invoice.component.ts:

import { Component, OnInit, AfterViewInit, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { AuthService } from '../../services/auth.service';
import { InvoiceService } from '../invoice.service';
import { Invoice } from '../invoiceModel';
import 'rxjs/add/operator/mergeMap';

@Component({
  selector: 'app-view-invoice',
  templateUrl: './view-invoice.component.html',
  styleUrls: ['./view-invoice.component.scss']
})

export class ViewInvoiceComponent implements OnInit, AfterViewInit {    
  userId: string;

  invoiceId: any;
  //    invoice: Observable<Invoice>;
  invoice: any;

  constructor(private authService: AuthService, private invoiceService: InvoiceService, private db: AngularFirestore, private route: ActivatedRoute) {
    this.userId = this.authService.user.uid;

    this.route.params.subscribe(params => {
        this.invoiceId = params.id;
    })

  this.db.collection('/users').doc(this.userId).collection('/invoices')
  .doc(this.invoiceId).ref.get().then(snapshot => {
        const data = snapshot.data();
        this.invoice = data;
    })
  }

  ngOnInit() {
    this.getInvoice();
  }

  ngAfterViewInit() {       
  }
}

1 个答案:

答案 0 :(得分:1)

负责获取发票数据的代码部分是异步的。因此,在构造函数中调用该方法时,在呈现HTML模板时,响应可能(并且几乎总是将)不可用。有几种方法可以防止这种情况发生。其中之一是简单地将HTML标记包装在ng-container中,只有在数据可用后才会呈现:

<ng-container *ngIf="invoice">
  <p>ID: {{ invoice.invoiceId }}</p>
  <p>Reference: {{ invoice.reference }}</p>
  <p>Date: {{ invoice.date | date: 'dd/MM/yyyy' }}</p>
</ng-container>