Edy Bourne
Edy Bourne

Reputation: 6187

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?

Upvotes: 10

Views: 10360

Answers (6)

Alex Strizhak
Alex Strizhak

Reputation: 990

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));
        }
      });
  }
});

Upvotes: 0

Ben Zhang
Ben Zhang

Reputation: 1281

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);
    }
  }
});

Upvotes: 2

zhisme
zhisme

Reputation: 2800

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' }
});

Upvotes: 1

Rodrigo Marroquim
Rodrigo Marroquim

Reputation: 46

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 (i.e. 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'});

Upvotes: 3

Navaneeth Pk
Navaneeth Pk

Reputation: 662

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`
});

Upvotes: 1

Russ
Russ

Reputation: 81

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`
});

Upvotes: 0

Related Questions