Angular Lifecycle Hook - Data loading initializes after the view initialization is complete

In my component, I have loaded a firestore document and converted it into a plain js object within the constructor. However, when trying to access the field values in the template, there is a slight delay in loading them. This results in an error being displayed in the browser console stating "Cannot read property 'id' of undefined" when trying to access {{invoice.id}}.

My understanding is that anything defined in the constructor should be immediately available in the view upon initialization. So, why is this error happening and how can I prevent it?

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

view-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() {       
  }
}

Answer №1

When fetching invoice data in the code, it's important to note that the process is asynchronous. This means that while the method may be called in the constructor, the response might not be available by the time the HTML template is rendered. To deal with this issue, there are a few solutions. One approach is to use ng-container to wrap the HTML tags so that they will only be displayed once the data is ready:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it necessary to specify the inputs property when defining an Angular @Component?

While exploring the Angular Material Button code, I came across something interesting in the @Component section - a declared inputs property. The description indicates that this is a list of class property names to data-bind as component inputs. It seems ...

Struggle with Loading Custom Templates in Text Editor (TinyMCE) using Angular Resolver

My goal is to incorporate dynamic templates into my tinyMCE setup before it loads, allowing users to save and use their own templates within the editor. I have attempted to achieve this by using a resolver, but encountered issues with the editor not loadin ...

Angular: Understanding Render Delay Caused by *ngIf and Expression Changes from Filters

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: false'. Current value: 'ngIf: true'. Encountering the above error in the console. In my code, I have filters that control ...

Keeping the Angular Material sidenav constantly expanded on desktop screens

I just started learning Angular and I'm attempting to implement the sidenar component from Angular Material (current version). Here is the code snippet inside the main-nav component: <mat-sidenav-container class="sidenav-container" autosize> ...

What is the best way to utilize data retrieved from an API call to dynamically populate a table in Angular?

My goal is to populate a table with information retrieved from an API call. However, I'm puzzled as to why the 'this.movies' array remains empty when I attempt to assign the data to it. https://i.sstatic.net/jpbXG.png https://i.sstatic.net ...

Typescript: Determine when a property should be included depending on the value of another property

Having some difficulty with Typescript and React. Specifically, I am trying to enforce a type requirement for the interface Car where the property colorId is only required if the carColor is set to 'blue'. Otherwise, it should not be included in ...

The message states that the variable "Chart" has not been defined

I have been attempting to integrate ChartJS with Angular2, but I keep encountering an error message stating that 'Chart is not defined'. I made sure to install the ChartJS typings and referenced them accordingly. Additionally, I included the char ...

Having trouble with assigning an error message in Formik validation using TypeScript

Currently, I am in the process of constructing a user input form in React & TypeScript using Formik. The form requires the user to input a name, email, and password. The input handling is functioning properly, but now I aim to implement validation functio ...

What is the most effective method for integrating Bootstrap CSS into an Angular project?

When incorporating a Bootstrap CSS file into an Angular project that has already been added using yarn add <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f2909d9d868186809382b2c6dcc3dcc3">[email protected]</a>, th ...

Jest encounters an issue while attempting to import Primeng CSS files

I am currently utilizing Jest version 26.6.3 for testing Angular components. Unfortunately, the unit tests for components that utilize Primeng's checkbox component are failing during the compileComponents step with the error message "Failed to load ch ...

Angular Error: The first argument has a property that contains NaN

Struggling with a calculation formula to find the percentage using Angular and Typescript with Angularfire for database storage. Encountered an error stating First argument contains NaN in property 'percent.percentKey.percentMale. The properties are d ...

Having trouble getting Angular ngIf to work with multiple matches?

I am facing an issue with my ngIf directive that has got me puzzled. Initially, my ngIf statement was functioning flawlessly like this. ngIf="this.offerFormGroup.get('identityTypeId').value == 4 However, now I need to extend it by adding mo ...

Do we need to import Vue in every component when using Nuxt with TypeScript?

I recently integrated TypeScript into Nuxt using the guidelines provided in the documentation: However, I have a specific question regarding component setup. Should I always include import vue from "vue" and export default Vue.extend ({}); in al ...

What sets npm start apart from firebase serve in terms of functionality and usage?

I have developed a new app that interacts with Firebase. The Firebase API has provided instructions for testing the application using commands like firebase serve and firebase deploy. When running firebase serve, a local server instance is created at local ...

Move the cursor to the end of the text when the key is released

I've developed a feature similar to that of a command line interface. When you input commands and hit the up key, the previous command is displayed. Everything is functioning as intended, but there's one minor issue. The current problem I'm ...

Launching npm start does not automatically open a browser tab

I'm currently learning angularjs 2 and I'm eager to create my first application using the framework. Following the guidelines on their official website, I proceeded with all the steps outlined in this link. In step 6, I am required to run the com ...

What is the best way to store the results of a Firestore Query in a variable?

I am facing an issue retrieving the values of apps in a query from Firestore. I am trying to use EJS to render the values of both the groups and the apps collection, but after the THEN statement from firestore, the values of apps are getting deleted and I ...

Share your Angular Elements web component as an npm module

Is there a way to package an Angular app as an npm module, especially when it is wrapped as a web component using Angular Elements? I'm interested in seamlessly importing the web component into another application through npm, rather than manually inc ...

Ways to apply the strategy pattern in Vue component implementation

Here's the scenario: I possess a Cat, Dog, and Horse, all of which abide by the Animal interface. Compact components exist for each one - DogComponent, CatComponent, and HorseComponent. Query: How can I develop an AnimalComponent that is capable of ...

Having trouble compiling Typescript code when attempting to apply material-ui withStyles function

I have the following dependencies: "@material-ui/core": "3.5.1", "react": "16.4.0", "typescript": "2.6.1" Currently, I am attempting to recreate the material-ui demo for SimpleListMenu. However, I am encountering one final compile error that is proving ...