1

I have an endpoint that returns this Json:

{
  "result": [
    {
      "id": 1,
      "name": "Kayak",
      "category": "Watersports",
      "description": "A boat for one person",
      "price": 27500,
      "currencyCode": "EUR"
    },
    {
      "id": 2,
      "name": "Lifejacket",
      "category": "Watersports",
      "description": "Protective and fashionable",
      "price": 48095,
      "currencyCode": "EUR"
    },
    {
      "id": 3,
      "name": "Soccer Ball",
      "category": "Soccer",
      "description": "FIFA-approved size and weight",
      "price": 1950,
      "currencyCode": "EUR"
    }
]
}

I have a class called Product in Angular:

import { Money, Currencies } from 'ts-money';

export class Product {
private money: Money;
public Amount = this.money.amount;

public constructor(
    public Id: number,
    public Name: string,
    public Category: string,
    public Price: number,
    public Description: string,
    public CurrencyCode: string) {
        this.money = new Money(Price, CurrencyCode);
    }

public GetPrice(): Money {
    return this.money;
}
}

I made this code in Angular:

export class ProductComponent implements OnInit {

  constructor(private datasource: ProductDataSource) {
  }

  private products: Product[];

  ngOnInit(): void {
    this.datasource.GetProducts()
    .subscribe((data) => {
        this.products = data;
    });
  }
 }
}

This code successfully returns an array of JSON objects that have the same properties as Product. Now, when I subscribe to this observable:

this.datasource.GetProducts()
.subscribe((data) => {
    // this.products is a class property of type Product[]
    this.products = data; // How do I make this work?
});

I can not figure out how to make the transition from JSON object to Angular class. My HTML page does not recognize this.products as an array of Product objects. What do I do?

yesman
  • 7,165
  • 15
  • 52
  • 117
  • How is declared / initialized `this.products` in your component and how are you using it in your template? Can you add this to your question please? – Maxime Lafarie Jan 15 '20 at 10:32

5 Answers5

4

I think it's because of your mapping in your product class and also the type of your class, try to change class Product to interface Product

like this

    export interface Product{

    public id: number;
    public name: string;
    public category: string;
    public price: number;
    public description: string;
    public currencyCode: string; 

 }

you can go take a look at Angular : Class and Interface for the differences between class and interface

EDIT : (as you can see in my code, I also changed the variable name to match with your JSON response)

Alann
  • 647
  • 5
  • 19
2

Another approach could be to make JSON data, compatible with your Product class. You could use the map rxjs operator to transform your JSON data into Product. Modify the get products code, like this

    const source$ = of(result).pipe(pluck('result'),map(item=> item.map(x=>{
      let product = new Product(x.id,x.name, x.category, x.price, x.description, x.currencyCode);
      return product;
    })));

Here is a StackBlitz link.

Obaid
  • 2,563
  • 17
  • 15
  • rxjs is a good approach, but using it with a `of` is odd. You may do the same thing inside `datasource.GetProducts()` method (which is not detailed in the question), directly on the http call – Random Jan 15 '20 at 10:52
  • Yes. Actually I just wrote this as an example only to reproduce the scenario in my stackblitz code. – Obaid Jan 15 '20 at 10:53
1

Product properties names and json properties names doesn't match. You can do it like this:

this.datasource.GetProducts()
  .subscribe((data) => {
    // this.products is a class property of type Product[]
    this.products = (data || []).map(item => new Product(item.id, item.name, item.category, item.price, item.description, item.currencyCode))
  });
qiAlex
  • 4,290
  • 2
  • 19
  • 35
0

create product interface with variables and use that interface to create array

    export interface Product{
      public Id: number,
      public Name: string,
      public Category: string,
      public Price: number,
      public Description: string,
      public CurrencyCode: string
    }

     products:Product[];
raharshi puli
  • 306
  • 2
  • 7
  • @Random it depend on how your project is set up, from the JSON you can see it's camelCase and not PascalCase – Alann Jan 15 '20 at 10:44
  • I'm talking about interface name, not attributes. Indeed attributes name depends on what the server responds, but should be camelCase (where in the question, attributes are PascalCase which is odd) – Random Jan 15 '20 at 10:46
0

Change class to interface and change the case of also.

export interface Product{

public id: number;
public name: string;
public category: string;
public price: number;
public description: string;
public currencyCode: string; }
uiTeam324
  • 1,215
  • 15
  • 34