How to serialize ember paginated data

556 Views Asked by At

I am getting following json from my rest API:

{
  "content": [{
    "id": 56789,
    "name": "sample book",
    "status": "available"
  },{
    "id": 56789,
    "name": "sample book",
    "status": "available"
  }],
  "last": true,
  "totalElements": 5,
  "totalPages": 2,
  "size": 3,
  "number": 1,
  "sort": null,
  "first": false,
  "numberOfElements": 2
}

Ember Book Model

export default DS.Model.extend({
  id: DS.attr(),
  name: DS.attr(),
  status: DS.attr()
});

Ember Route

import Ember from 'ember';
import RouteMixin from 'ember-cli-pagination/remote/route-mixin';

export default Ember.Route.extend(RouteMixin, {

  model: function(params) {
      params.paramMapping = {
        perPage: "size"
      };
      return this.findPaged('book',params);
  }
});

In the Firefox network tab i can able to see the response but in browser console i am getting the following message:

Error while processing route: book.index data is undefined _pushInternalModel

In Chrome getting following exception:

ember.debug.js:30610 Error while processing route: books.index Cannot read property 'type' of undefined TypeError: Cannot read property 'type' of undefined

I am using following versions of ember:

  • "ember-cli": "2.5.0",
  • "ember-cli-pagination": "2.2.2"

I think i should serialize the response using "normalizeResponse" but i don't know how to do it.

As per Lux comment changed serializer :

import JSONSerializer from 'ember-data/serializers/json';
import DS from'ember-data';

export default DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
    product: {embedded: 'always'}
},
extractMeta(store, typeClass, payload) {
  let meta = [{
  "last": payload.last,
  "totalElements": payload.totalElements,
  "totalPages": payload.totalPages,
  "size": payload.size,
  "number": payload.number,
  "sort": payload.sort,
  "first": payload.first,
  "numberOfElements": payload.numberOfElements
}];
delete payload.content;
delete payload.last;
delete payload.totalElements;
delete payload.totalPages;
delete payload.size;
delete payload.number;
delete payload.sort;
delete payload.first;
delete payload.numberOfElements;

return meta;
},
normalizeArrayResponse(store, primaryModelClass, payload, id, requestType) {
let documentHash = {
  data: [],
  included: [],
  meta: this.extractMeta(store, primaryModelClass, payload),
};
payload.content.forEach(item => {
  let { data, included } = this.normalize(primaryModelClass, item);
if (included) {
  documentHash.included.push(...included);
}
documentHash.data.push(data);
});
}
});

Getting following error :

ember.debug.js:19750 TypeError: Cannot read property 'forEach' of undefined
at Class.normalizeArrayResponse (device.js:41)
at Class.normalizeQueryResponse (json.js:333)
at Class.normalizeResponse (json.js:228)
1

There are 1 best solutions below

7
Lux On

You should checkout the documentation.

I think you would have to implement extractMeta:

extractMeta(store, typeClass, payload) {
  let meta = [{
    "last": payload.last,
    "totalElements": payload.totalElements,
    "totalPages": payload.totalPages,
    "size": payload.size,
    "number": payload.number,
    "sort": payload.sort,
    "first": payload.first,
    "numberOfElements": payload.numberOfElements
  }];
  delete payload.content;
  delete payload.last;
  delete payload.totalElements;
  delete payload.totalPages;
  delete payload.size;
  delete payload.number;
  delete payload.sort;
  delete payload.first;
  delete payload.numberOfElements;

  return meta;
}

included are other included records. Informations like pagination data should be in the meta hash. So ember is thinking you provide it with additional records, but can't find the type of them.

Next you implement normalizeArrayResponse. Probably something like this will work for you:

normalizeArrayResponse(store, primaryModelClass, payload, id, requestType) {
  let documentHash = {
    data: [],
    included: [],
    meta: this.extractMeta(store, primaryModelClass, payload),
  };

  payload.content.forEach(item => {
    let { data, included } = this.normalize(primaryModelClass, item);
    if (included) {
      documentHash.included.push(...included);
    }
    documentHash.data.push(data);
  });
}

This is to extract your data from the content array.