Is it possible to store a query in variable?

I’m actually using ember-simple-pagination. It’s works with a simple logic : -Empty the sore -Fetch data according to the actual page

The fact is that transition is not smooth at all, see by yourself : https://streamable.com/sg6sg

Is there a way to fix that ? My mind said to me that it would be a solution to fetch data first, empty the sort and then push data back to the store.

import Component from '@ember/component';
import { computed } from '@ember/object';
import { sort } from '@ember/object/computed';
import { inject as service } from '@ember/service';

export default Component.extend({
  store: service(),
  posts: computed(function() {
    return this.get('store').peekAll('post');
  }),

  pageSize: 20,
  pageNumber: null,
  recordCount: null,

  sortProps: ['createdAt:desc'],
  sortedPosts: sort('posts', 'sortProps'),

  loadPosts(getPageNumber) {
    const pageSize = this.get('pageSize');

    this.get('store').unloadAll('post');
    this.get('store').
      query('post', {page: {number: getPageNumber, size: pageSize}}).
      then((result) => {
        this.setProperties({
            'recordCount': result.get('meta.record-count'),
            'pageNumber': getPageNumber
        });
      };
  },

  init() {
    this._super(...arguments);
    this.loadPosts(1);
  },

  actions: {
    getPage(getPageNumber) {
      this.loadPosts(getPageNumber);
    }
  }
});

Hi @linkref,

I think the problem here is that you’re rendering everything in the store, which makes it hard to control exactly what’s shown. You could instead control directly which list of posts is being shown. Then there would be no need to unload first (which is causing the visual problem of your list disappearing before the new page has loaded).

Also, when you’re loading data in a component like this you need to deal with asynchrony. If the user clicks faster than the server can respond, you’re going to end up in weird states. Also if the user navigates away and this component is destroyed while a query is still running, you’ll get an exception. For those reasons I’d recommend using ember-concurrency.

Here’s a sketch of an alternative solution, I didn’t run this so I probably typed something wrong:

import Component from '@ember/component';
import { computed } from '@ember/object';
import { sort } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import { task } from 'ember-concurrency';

export default Component.extend({
  store: service(),

  pageSize: 20,
  pageNumber: null,
  recordCount: null,

  sortProps: ['createdAt:desc'],
  sortedPosts: sort('posts', 'sortProps'),

  loadPosts: task(function * (getPageNumber) {
    const pageSize = this.get('pageSize');
    let result = yield this.get('store').query('post', {page: {number: getPageNumber, size: pageSize}});
    this.setProperties({
      'posts': result.toArray(),
      'recordCount': result.get('meta.record-count'),
      'pageNumber': getPageNumber
    });
  }).restartable(),

  init() {
    this._super(...arguments);
    this.set('posts'), []);
    this.loadPosts.perform(1);
  },

  actions: {
    getPage(getPageNumber) {
      this.set('pageNumber', getPageNumber);
    }
  }
});
1 Like