Benjamin
Benjamin

Reputation: 3826

Cannot read property of undefined when using interpolation

I have put an effort before asking this question to search and make sure this question is not duplicated, but I didn't find anything similar to my issue.

I am newbie to Angular 2, and my component class is like below:

import {Component} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';

@Component({
 selector: 'pm-products',
 templateUrl: 'app/products/product-list.component.html'
})

export class ProductListComponent{
pageTitle: string = 'Product List';
products: any[] = [   
    {
        "productId": 1,
        "productName": "Leaf Rake",
        "productCode": "GDN-0011",
        "releaseDate": "March 19, 2016",
        "description": "Leaf rake with 48-inch wooden handle.",
        "price": 19.95,
        "starRating": 3.2,
        "imageUrl": "SOME URL"
    },
    {
        "productId": 2,
        "productName": "Garden Cart",
        "productCode": "GDN-0023",
        "releaseDate": "March 18, 2016",
        "description": "15 gallon capacity rolling garden cart",
        "price": 32.99,
        "starRating": 4.2,
        "imageUrl": "SOME URL"
    }

    ];
}

And below code is my view:

<div class='table-responsive'>
    <table class='table' 
        *ngIf='products && products.length'>
        <thead>
            <tr>
                <th>
                    <button class='btn btn-primary'>
                        Show Image
                    </button>
                </th>

                <th>Product</th>
                <th>Code</th>
                <th>Available</th>
                <th>Price</th>
                <th>5 Star Rating</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor='let product of products'></tr>
            <td></td>
            <td>{{ product.productName }}</td>
            <td>{{ product.productCode }}</td>
            <td>{{ product.releaseDate }}</td>
            <td>{{ product.price }}</td>
            <td>{{ product.starRating }}</td>

        </tbody>
    </table>

</div>

When I run this code I get an error saying "Error in app/products/product-list.component.html:38:16 caused by: Cannot read property 'productName' of undefined", and "Cannot read property 'productName' of undefined"

Using the interpolation in my view, my expectation is to see the products object properties values within the tags.

Upvotes: 0

Views: 3536

Answers (3)

Vivek Doshi
Vivek Doshi

Reputation: 58543

The only issue with your code is

<tr *ngFor='let product of products'></tr>
<td></td>
<td>{{ product.productName }}</td>
<td>{{ product.productCode }}</td>
<td>{{ product.releaseDate }}</td>
<td>{{ product.price }}</td>
<td>{{ product.starRating }}</td>
-------------------------------------------
<tr *ngFor='let product of products'></tr>

Here you are looping through tr tag , so td tag will never get any value of product , because of that you are getting error of

"Error in app/products/product-list.component.html:38:16 caused by: Cannot read property 'productName' of undefined", and "Cannot read property 'productName' of undefined"

If you will inspect element and check the output you will get ,

And there is no need of using any "Elvis operator" , as you are already providing data via component and before view loaded.

Last code should be like

<tr *ngFor='let product of products'>
    <td></td>
    <td>{{ product.productId }}</td>
    <td>{{ product.productCode }}</td>
    <td>{{ product.releaseDate }}</td>
    <td>{{ product.price }}</td>
    <td>{{ product.starRating }}</td>
</tr>

Upvotes: 1

seidme
seidme

Reputation: 13048

Use Angular safe navigation operator to check nested properties' path. Try this:

<tbody>
    <tr *ngFor='let product of products'>
        <td></td>
        <td>{{ product?.productName }}</td>
        <td>{{ product?.productCode }}</td>
        <td>{{ product?.releaseDate }}</td>
        <td>{{ product?.price }}</td>
        <td>{{ product?.starRating }}</td>
     </tr>
</tbody>

Upvotes: 2

Hristo Eftimov
Hristo Eftimov

Reputation: 15713

You don't need to close your <tr> there. Actually you "close" the ngFor loop on the same level and product is undefined. You have to close is after your <td> cells.

This works:

<tbody>
    <tr *ngFor='let product of products'>
        <td></td>
        <td>{{ product.productName }}</td>
        <td>{{ product.productCode }}</td>
        <td>{{ product.releaseDate }}</td>
        <td>{{ product.price }}</td>
        <td>{{ product.starRating }}</td>
     </tr>
</tbody>

Upvotes: 3

Related Questions