Search code examples
angulartypescriptmodelionic4

Ionic 4 angular data.map is not a function


I'm trying to store a response from my http request into a model. I followed this guide and managed to pass the data into the model. However I think I am doing it wrong as I can't get it to display on the html and the output I am seeing from the console is a little jumbled up.

I believe my error is in accessing the json response, but I can't seem to find the error. Can anyone help point out my error?

My models.

// data.model.ts
import { Fruits } from './fruitsId.model';
import { Deserializable } from './deserialize.model';

export class Data implements Deserializable {
  data: Fruits[];

  deserialize(input: any): this {
    Object.assign(this, input);
    this.data = input.data.map(data => new Fresh().deserialize(data));

    return this;
  }
}
// fruits.model.ts
import { Deserializable } from './deserialize.model';
import { FruitsId } from './fruitsId.model';
import { CustomerId } from './customerId.model';
import { StoreId } from './storeId.model';

export class Fresh implements Deserializable {
    public fruitsId: FruitsId;
    public time: string;
    public customerId: CustomerId;
    public storeId: StoreId;
    public name: string;
    public text: string;

    deserialize(input: any): this {
    Object.assign(this, input);
    this.fruitsId = new FreshId().deserialize(input.freshId);
    this.customerId = new HumanId().deserialize(input.humanId);
    this.storeId = new MasterId().deserialize(input.masterId);

    return this;
    }
}
// fruitsId.model.ts
import { Deserializable } from './deserialize.model';

export class FruitsId implements Deserializable {
    type: string;
    id: string;

    deserialize(input: any): this {
       return Object.assign(this, input);
    }
}

Followed by customerId.model.ts and storeId.model.ts with the same format as freshId.model.ts.

My Service.

// fruits.service.ts
public getAllThings(): Observable<any> {
// Some httpOptions here
// ...
return this.http
  .get(`${this.url}`, httpOptions)
  .pipe(
    // ERROR HERE: data.map is not a function
    map(data => data.map(data => new Data().deserialize(data))),
  );
}

Sample response from HTTP GET.

{
  "data": [
    {
      "id": {
        "type": "red",
        "id": "123"
      },
      "time": 1579677349193,
      "customerId": {
        "type": "retailer",
        "id: "234"
      },
      "storeId": {
        "type": "abc Store",
        "id": "001"
      },
      "name": "Apple",
      "text": "very delicious"
    }
  ]
}

Finally at the home.page.ts

// Some imports
// ...

export class DashboardPage implements OnInit {

  fruitsList: any = [];
  data: Data[];

  constructor(private fruitsService: FruitsService) { }

  ionViewWillEnter() {
    this.getFruits();
  }

  getFruits() {
    this.fruitsService.getFreshes().subscribe(
      res => this.data = res
    );
  }

}

Solution

  • Author of the guide here.

    Your response is not an array, but calling .map on the response assumes exactly that. Looking at your Response the correct deserialization would be

    map(response => response.data.map(...))
    

    since data would just be the entire response which holds the actual data in a data property.

    You can always look at the shape of your response by replacing the lambda function with:

    map(response => {
      console.log(response);
      return response.data.map(...);
    })