Search code examples
ember.jsresponsestoremeta

Losing tons of ember-data class attributes when assigning query response to model field


In my EmberJS app, I have two models, Book and Page. Book has a hasMany relationship to Page. In my controller to edit a single book, I am making a query to get all pages related to that book, and then assigning the response from the query back to the Book's page field.

I am using a third party EmberJS library ember-models-table to make paginated tables. I pass in book.pages to the paginated table component, and all works fine, except when I want to actually move between pages of results. The version of ember-models-table I'm using expects certain fields on book.pages to be present when paginating results: meta, query, store, and type.modelName. I can explicitly set those fields onto book.pages, but I have a feeling there has got to be a better way. Why would EmberJS strip fields like meta and store, from an ember-data query response, when you set that response onto another object?

Controller

this.get('store').query('page', { bookId }).then((res) => {
    set(book, 'pages', res);

    // Third Party Paginated Table Component Requires These Fields
    set(book, 'pages.meta', res.get('meta'));
    set(book, 'pages.query', res.get('query'));
    set(book, 'pages.store', res.get('store'));
    set(book, 'pages.type.modelName', res.get('type.modelName'));
});

HBS - Pages table

{{models-table-paginated
  data=book.pages
  columns=columns
  customClasses=(hash table='table table-condensed')
  showGlobalFilter=false
  showColumnsDropdown=false
  selectRowOnClick=false
  pageSize=10
}}

Solution

  • You need to edit your serializer too. For example, i use models-table too but in backend, i use Django adapter. So i had to edit the serializer for each model to calculate the remaining pages (totalPages) and form that number to make the pagination based on your pageSize. Also at query on your route, you need to set pageSize and page as default. Now if you don't use meta like Django you should check your adapter documentation

    for example, in Django the serializer for book model will be like this

    import DRFSerializer from './drf';
    import DS from 'ember-data';
    import { isNone } from '@ember/utils';
    
    export default DRFSerializer.extend(DS.EmbeddedRecordsMixin,{
      extractMeta: function(store, type, payload) {
        let meta = this._super(store, type, payload);
        if (!isNone(meta)) {
          // Add totalPages to metadata.
          let totalPages = 1;
          if (!isNone(meta.next)) {
            // Any page that is not the last page.
            totalPages = Math.ceil(meta.count / payload[type.modelName].length);
          } else if (isNone(meta.next) && !isNone(meta.previous)) {
            // The last page when there is more than one page.
            totalPages = meta.previous + 1;
          }
          meta['totalPages'] = totalPages;
        }
        return meta;
      }