1
votes

I'm trying to display a Product which I get from a local server in a template of my Product component. This template is supposed to be displayed in the template of my app.component. I can successfully instantiate a productModel instance from within my app.component.ts controller but when I try to display the product in a table on my app.component.html template I get the following error: Any idea where I can look for the issue?

My error:

error_handler.js:48EXCEPTION: Error in ./ProductComponent class ProductComponent - inline template:8:4 caused by: Cannot read property 'Description' of undefinedErrorHandler.handleError @ error_handler.js:48 error_handler.js:50ORIGINAL EXCEPTION: Cannot read property 'Description' of undefinedErrorHandler.handleError @ error_handler.js:50 error_handler.js:53ORIGINAL STACKTRACE:ErrorHandler.handleError @ error_handler.js:53 error_handler.js:54TypeError: Cannot read property 'Description' of undefined at _View_ProductComponent0.detectChangesInternal (component.ngfactory.js:128) at _View_ProductComponent0.AppView.detectChanges (view.js:233) at _View_ProductComponent0.DebugAppView.detectChanges (view.js:338) at _View_AppComponent0.AppView.detectViewChildrenChanges (view.js:259) at _View_AppComponent0.detectChangesInternal (component.ngfactory.js:126) at _View_AppComponent0.AppView.detectChanges (view.js:233) at _View_AppComponent0.DebugAppView.detectChanges (view.js:338) at _View_AppComponent_Host0.AppView.detectViewChildrenChanges (view.js:259) at _View_AppComponent_Host0.detectChangesInternal (host.ngfactory.js:33) at _View_AppComponent_Host0.AppView.detectChanges (view.js:233)ErrorHandler.handleError @ error_handler.js:54 error_handler.js:57ERROR CONTEXT:ErrorHandler.handleError @ error_handler.js:57 error_handler.js:58DebugContextErrorHandler.handleError @ error_handler.js:58 zone.js:388Unhandled Promise rejection: Error in ./ProductComponent class ProductComponent - inline template:8:4 caused by: Cannot read property 'Description' of undefined ; Zone: ; Task: Promise.then ; Value: ViewWrappedError TypeError: Cannot read property 'Description' of undefined at _View_ProductComponent0.detectChangesInternal (/AppModule/ProductComponent/component.ngfactory.js:128:62) at _View_ProductComponent0.AppView.detectChanges (http://localhost:4200/main.bundle.js:56051:14) at _View_ProductComponent0.DebugAppView.detectChanges (http://localhost:4200/main.bundle.js:56156:44) at _View_AppComponent0.AppView.detectViewChildrenChanges (http://localhost:4200/main.bundle.js:56077:19) at _View_AppComponent0.detectChangesInternal (/AppModule/AppComponent/component.ngfactory.js:126:8) at _View_AppComponent0.AppView.detectChanges (http://localhost:4200/main.bundle.js:56051:14) at _View_AppComponent0.DebugAppView.detectChanges (http://localhost:4200/main.bundle.js:56156:44) at _View_AppComponent_Host0.AppView.detectViewChildrenChanges (http://localhost:4200/main.bundle.js:56077:19) at _View_AppComponent_Host0.detectChangesInternal (/AppModule/AppComponent/host.ngfactory.js:33:8) at _View_AppComponent_Host0.AppView.detectChanges (http://localhost:4200/main.bundle.js:56051:14)consoleError @ zone.js:388 zone.js:390Error: Uncaught (in promise): Error: Error in ./ProductComponent class ProductComponent - inline template:8:4 caused by: Cannot read property 'Description' of undefined(…)consoleError @ zone.js:390

My product component template:

<table class="table-responsive">
<tr>
<th>Description</th>
<th>POS Description</th>
<th>POS Price</th>
<th>Stock On Hand</th>
</tr>
<tr>
<td>{{product.Description}}</td>
<td>{{product.POSDescription}}</td>
<td>{{product.POSPrice}}</td>
<td>{{product.StockOnHand}}</td>
</tr>
</table>

My product component controller:

import { Component, OnInit, Input } from '@angular/core';

import { ProductModel } from '../../models/product.model';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css'],
  host: {
      class : 'row'
  }

})
export class ProductComponent implements OnInit {
    @Input() product: ProductModel;

  constructor() { }

  ngOnInit() {
  }

}

My app.component template:

<div class="row">
<div class="col-md-6 col-md-push-3">
<form class="form-horizontal" role="form">
    <div class="form-group">        
        <input type="number" class="form-control" id="barcode" placeholder="Enter Barcode" #barcode>    
    </div>
    <button class="btn btn-submit btn-block" (click)="submitBarcode(barcode)">Submit</button>
</form>
</div>
</div>
<div class="row">
    <app-product [product]="product"></app-product>-->
</div>

My app component controller:

import { Component } from '@angular/core';

import { RestService } from "./services/rest.service";
import { ProductModel } from "./models/product.model";


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

    product: ProductModel;

    constructor(private restService: RestService){

    }

submitBarcode(barcode: HTMLInputElement){

    this.restService.getProduct(barcode.value)
    .subscribe(
    (res) => {
        this.product = new ProductModel(res.BaseURI, res.CustomError, res.ProviderName, res.RequestFormData, res.RequestURI, res.ResponseCode, res.AvgQty1, res.AvgQty2, res.AvgQty3, res.BarCode, res.Description, res.POSDescription, res.POSPrice, res.ProductCode, res.PurchCount, res.StockOnHand);
        console.log("returned product description: " + this.product.Description);
        //console.log(res);
    },
    (res) => {
        console.log("failure" + res);
    }
    );
    //console.log("product: " + product);
}

}
2

2 Answers

3
votes

That's because product is not defined until your http call is finished. You can use safe navigation operator (?) to protect your template from getting current error until your data arrive:

<table class="table-responsive">
<tr>
<th>Description</th>
<th>POS Description</th>
<th>POS Price</th>
<th>Stock On Hand</th>
</tr>
<tr>
<td>{{product?.Description}}</td>
<td>{{product?.POSDescription}}</td>
<td>{{product?.POSPrice}}</td>
<td>{{product?.StockOnHand}}</td>
</tr>
</table>

You can also use NgIf directive which will add your table to DOM after http call is finished:

<table *ngIf="product" class="table-responsive">
<tr>
<th>Description</th>
<th>POS Description</th>
<th>POS Price</th>
<th>Stock On Hand</th>
</tr>
<tr>
<td>{{product.Description}}</td>
<td>{{product.POSDescription}}</td>
<td>{{product.POSPrice}}</td>
<td>{{product.StockOnHand}}</td>
</tr>
</table>
0
votes

You can use *ngIf as this:

<table *ngIf="product" class="table-responsive">
 <tr>
  <th>Description</th>
  <th>POS Description</th>
  <th>POS Price</th>
  <th>Stock On Hand</th>
</tr>
<tr>
  <td>{{product.Description}}</td>
  <td>{{product.POSDescription}}</td>
  <td>{{product.POSPrice}}</td>
  <td>{{product.StockOnHand}}</td>
  </tr>
</table>