Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking data for Angular2/typescript with my own model type properties

I'm new in the Angular2 world. For learning Angular I followed different tutorials and now I try to build a shop to learn more. But i get stuck right away.

I'm trying to get this model in to Angular: enter image description here

But I'm not succeeding. I get different errors like.

TypeError: Cannot read property 'description' of undefined and error TS2322: Type '{ ... }' is not assignable to type 'Product[]'.Type ...

This is what i got so far:

Product-type-attribute-model

export class ProductTypeAttribute {
id: number;
name: string;
content: string;
}

Product-type-model

import { ProductTypeAttribute } from './product-type-attribute.model';

export class ProductType {
    id: number;
    name: string;
    description: string;
    attributeTypes: ProductTypeAttribute[];
}

Product-model

import { ProductType} from './product-type.model';

export class Product  {
    id: number;
    name: string;
    description: string;
    image: string;
    price: number;
    type: ProductType;
}

Mock-product

import { Product } from './product.model';
import { ProductType } from './product-type.model';
import { ProductTypeAttribute } from './product-type-attribute.model';

export const productTypeAttributes: ProductTypeAttribute[] = [
    {
        id: 1,
        name: 'Kleur',
        content: 'test'
    },
    {
        id: 2,
        name: 'test',
        content: 'test'
    },
    {
        id: 3,
        name: 'test',
        content: 'test'
    },
    {
        id: 4,
        name: 'test',
        content: 'test'
    }
];

export const productTypeAttributes2: ProductTypeAttribute[] = [
    {
        id: 5,
        name: 'Kleur',
        content: 'test'
    },
    {
        id: 6,
        name: 'test',
        content: 'test'
    },
    {
        id: 7,
        name: 'test',
        content: 'test'
    },
    {
        id: 8,
        name: 'test',
        content: 'test'
    }
];

export const productType: ProductType =
    {
        id: 1,
        name: 'Type 1',
        description: 'Description of type 1',
        attributeTypes: productTypeAttributes
    };

export const productType2: ProductType =
    {
        id: 2,
        name: 'Type 2',
        description: 'Description of type 2',
        attributeTypes: productTypeAttributes2
    };

export const products: Product[] = [
    {
        id: 1,
        name: 'Product 1',
        description: 'Description of product 1',
        image: 'https://www.google.nl/imgres?imgurl=https%3A%2F%2Fangular.io%2Fresources%2Fimages%2Flogos%2Fangular2%2Fangular.svg&imgrefurl=https%3A%2F%2Fangular.io%2F&docid=bJoyJcb-C12SHM&tbnid=G_BYSyR7DGpqqM%3A&vet=1&w=800&h=800&bih=1060&biw=1060&q=angular2&ved=0ahUKEwjdrq6it87RAhUEExoKHdXlAYIQMwgcKAAwAA&iact=mrc&uact=8',
        price: 15.15,
        type: productType
    },
    {
        id: 2,
        name: 'Product 2',
        description: 'Description of product 2',
        image: 'https://www.google.nl/imgres?imgurl=https%3A%2F%2Fangular.io%2Fresources%2Fimages%2Flogos%2Fangular2%2Fangular.svg&imgrefurl=https%3A%2F%2Fangular.io%2F&docid=bJoyJcb-C12SHM&tbnid=G_BYSyR7DGpqqM%3A&vet=1&w=800&h=800&bih=1060&biw=1060&q=angular2&ved=0ahUKEwjdrq6it87RAhUEExoKHdXlAYIQMwgcKAAwAA&iact=mrc&uact=8',
        price: 15.15,
        type: productType
    },
    {
        id: 3,
        name: 'Product 3',
        description: 'Description of product 3',
        image: 'https://www.google.nl/imgres?imgurl=https%3A%2F%2Fangular.io%2Fresources%2Fimages%2Flogos%2Fangular2%2Fangular.svg&imgrefurl=https%3A%2F%2Fangular.io%2F&docid=bJoyJcb-C12SHM&tbnid=G_BYSyR7DGpqqM%3A&vet=1&w=800&h=800&bih=1060&biw=1060&q=angular2&ved=0ahUKEwjdrq6it87RAhUEExoKHdXlAYIQMwgcKAAwAA&iact=mrc&uact=8',
        price: 15.15,
        type: productType2
    }
];

Product-service

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

import { Product } from './../shared/product.model';
import { products } from './../shared/mock-products';

@Injectable()
export class ProductService {
    getProducts(): Promise<Product[]> {
        return Promise.resolve(products);
    }

    getProduct(id: number): Promise<Product> {
        return this.getProducts().then(products => products.find(product => product.id === id));
    }
}

Product-component

import { Component, OnInit } from '@angular/core';
import { Product } from './../shared/product.model';
import { ProductService } from './../product/product.service';

@Component({
    selector: 'product',
    template: require('./product.component.html'),
    providers: [ProductService]
})

export class ProductComponent implements OnInit {
    product: Product;

    constructor(private productService: ProductService) { }

    getProduct(): void {
        this.productService.getProduct(1).then(product => this.product = product);
    }

    ngOnInit(): void {
        this.getProduct();
    }
}

Product HTML

<div class="product">
<div class="header">
        <h1>{{product?.name}}</h1>
        <h4></h4>
</div>

<figure>
    <img src="{{product?.image}}">
</figure>

<section>
    <p>{{product?.description}}</p>
    <details>
        <summary>Product Features</summary>
        <ul>
            <li *ngFor="let productAttribute of product?.type?.attributeTypes">
                {{productAttribute?.name}}
            </li>
        </ul>
    </details>
    <button>Buy Now</button>
</section>

I hope I explained my problem well and that you guys can help me out here.

UPDATE enter image description here

*UPDATE** Okay, now things are getting crazy. When i do this

export const products: ({ id: number;description: string;image: string;price: number;type: Object } |
{ id: number;name: string;description: string;image: string;price: number;type: Object })[] = [
{
    id: 1,
    description: "Description of product 1",
    image: "https://www.google.nl/imgres?imgurl=https%3A%2F%2Fangular.io%2Fresources%2Fimages%2Flogos%2Fangular2%2Fangular.svg&imgrefurl=https%3A%2F%2Fangular.io%2F&docid=bJoyJcb-C12SHM&tbnid=G_BYSyR7DGpqqM%3A&vet=1&w=800&h=800&bih=1060&biw=1060&q=angular2&ved=0ahUKEwjdrq6it87RAhUEExoKHdXlAYIQMwgcKAAwAA&iact=mrc&uact=8",
    price: 15.15,
    type: productType
},
{
    id: 2,
    name: "Product 2",
    description: "Description of product 2",
    image: "https://www.google.nl/imgres?imgurl=https%3A%2F%2Fangular.io%2Fresources%2Fimages%2Flogos%2Fangular2%2Fangular.svg&imgrefurl=https%3A%2F%2Fangular.io%2F&docid=bJoyJcb-C12SHM&tbnid=G_BYSyR7DGpqqM%3A&vet=1&w=800&h=800&bih=1060&biw=1060&q=angular2&ved=0ahUKEwjdrq6it87RAhUEExoKHdXlAYIQMwgcKAAwAA&iact=mrc&uact=8",
    price: 15.15,
    type: productType
},
{
    id: 3,
    name: "Product 3",
    description: "Description of product 3",
    image: "https://www.google.nl/imgres?imgurl=https%3A%2F%2Fangular.io%2Fresources%2Fimages%2Flogos%2Fangular2%2Fangular.svg&imgrefurl=https%3A%2F%2Fangular.io%2F&docid=bJoyJcb-C12SHM&tbnid=G_BYSyR7DGpqqM%3A&vet=1&w=800&h=800&bih=1060&biw=1060&q=angular2&ved=0ahUKEwjdrq6it87RAhUEExoKHdXlAYIQMwgcKAAwAA&iact=mrc&uact=8",
    price: 15.15,
    type: productType2
}

It gives no errors, but does not show the name.

like image 444
apero Avatar asked Sep 02 '25 17:09

apero


1 Answers

Actually tested your code, there only seems to be async problem. Try using the safe operator: ? (otherwise also called elvis-operator) like so:

<h1>{{product?.name}}</h1>

The other option is to use *ngIf like so:

<h1 *ngIf="product">{{product.name}}</h1>

More about the elvis-operator here. This comes really handy in Angular (2) apps, since we are constantly dealing with async operations, since (usually) the view is rendered before data is received.

If you prefer *ngIf this also works, app won't throw error since the code you have wrapped inside it, is only rendered when there is data present, in this case in your product object.

Working Plunker

You could change your classes to interfaces instead, so:

export interface Product  {
    id: number;
    name: string;
    description: string;
    image: string;
    price: number;
    type: ProductType;
}

or add constructor to your classes:

export class Product  {
    constructor(
      public id: number,
      public name: string,
      public description: string,
      public image: string,
      public price: number,
      public type: ProductType
    ) { }
}
like image 60
AT82 Avatar answered Sep 05 '25 08:09

AT82