简体   繁体   中英

Ember-data find record by id and also additional parameters?

In the Ember docs I found that find() has support for finding by id:

this.store.find('post', 1); // => GET /posts/1

And also by passing arbitrary parameters:

this.store.find('post', { name: "Peter" }); // => GET to /posts?name='Peter'

But in my case I must find by id, and pass an additional parameter to request all fields to be included in the response (some are omitted by default), like so:

this.store.find('post', 1); // => GET /posts/1?include=all

I tried to do it this way:

this.get('store').find('post', params.post_id, { include : 'all' });

But my params were ignored.

This seems a fairly basic use case so I must be missing something...

How can I accomplish this?

You may have found a workaround the problem by now, but the way to go is to use the adapterOptions on the options argument.

So, let's go:

  1. Where you fetch the model (ie a route), setup the custom argument you want. In your case, the include. It goes like this:

     //file app/routes/post/edit.js import Ember from 'ember'; export default Ember.Route.extend({ model: function(params) { return this.store.findRecord('post', params.post_id, { adapterOptions: { include: 'all' } }); } }); 
  2. Read this value inside the model's adapter to customize the ajax request:

     //file app/adapters/post.js export default JSONAPIAdapter.extend({ findRecord: function(store, type, id, snapshot) { if (Em.get(snapshot, 'include')) { let url = this.buildURL(type.modelName, id, snapshot, 'findRecord'); let query = this.buildQuery(snapshot); return this.ajax(url, 'GET', { data: query }); } else { this._super(...arguments); } }); 

UPDATE 1:

On the ember-data newer versions (>= 2.4.0) you can do it out of the box, by calling store.findRecord('post', {include: 'all'});

PhStoned's code works but would cause errors if adapterOptions is blank. Here is an improved version.

import Ember from 'ember';
import applicationAdapter from './application';

export default applicationAdapter.extend({
  findRecord: function(store, type, id, snapshot) {
    if (snapshot.adapterOptions)) {
      let url = this.buildURL(type.modelName, id, snapshot, 'findRecord');
      let query = {
        include: Ember.get(snapshot.adapterOptions, 'include')
      };
      return this.ajax(url, 'GET', { data: query });
    } else {
      return this._super(...arguments);
    }
  }
});

You can use queryRecord instead of find if you want to pass additional params to backend.

this.store.queryRecord('post', { id: params.post_id, include: 'all' }).then(function(data) {
  // do something with `data`
});

Rodrigo Marroquim answer didn't work for me. So I've come to the following solution
Ember v2.6.0

import Ember from 'ember';
import applicationAdapter from './application';

export default applicationAdapter.extend({
  findRecord: function(store, type, id, snapshot) {
    if (Ember.get(snapshot.adapterOptions, 'include')) {
      let url = this.buildURL(type.modelName, id, snapshot, 'findRecord');
      let query = {
        include: Ember.get(snapshot.adapterOptions, 'include')
      };
      return this.ajax(url, 'GET', { data: query });
    } else {
      this._super(...arguments);
    }
  }
});

usage:

this.get('store').findRecord('modelName', id, {
          adapterOptions: { include: 'all' }
});

My suggestion would be to try using the query function rather than the find function. This will allow you to query an unlimited number of filters.

var myStore = this.get('store');
myStore.query('post', { 
    _id: params.post_id,
    include : 'all'
 }).then(function(peters) {
      // Do something with `peters`
});

May helpful to use ajax with adapter implementation here:

const { getOwner } = Ember;
let adapter = getOwner(this).lookup('adapter:application');
adapter.ajax(
  adapter.buildURL(`posts/${id}`), 'GET', { data: { include: 'all' } }
);

#> /posts/1?include=all

This ajax solution even better:

const { inject: { service } } = Ember;

export default Ember.Route.extend({
  ajax: service(),

  async model(params) {
    let id = params.id;

    return await this.get('ajax')
      .request(`/posts/${id}`, {
        data: { include: 'all' }
      }).then(({ post }) => {
        if (post) {
          return this.store.push(this.store.normalize('post', post));
        }
      });
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM