通过链接查询异步hasMany中的参数

时间:2014-01-20 14:10:56

标签: ember.js ember-data

使用Ember Data,您可以执行以下操作:

App.Post = DS.Model.extend({
   comments: DS.hasMany('comment', {async:true})
});

使用links - 从服务器返回的对象或序列化有效负载客户端,如下所示:

{
  post:{
    id: 1,
    links: {
      comments: 'comments'
    }
  }
}

当您执行/post/:post_id/comments

时,Ember数据会生成以下网址post.get('comments')

但我收到了很多评论,我想将查询参数传递给它(就像在ember数据中进行常规搜索一样):post.get('comments',{ from: '2014-01-01', to: '2014-01-07' });

不幸的是它没有用。还有另一种方式吗?

另请参阅我的其他question

3 个答案:

答案 0 :(得分:4)

有很多方法可以实现这一目标,我会把它们全部列出然后决定哪个看起来最好,

更改从服务器返回的json(可能是最正确的)

{
  post:{
    id: 1,
    links: {
      comments: 'comments?from=foo&to=bar'
    }
  }
}

示例:http://emberjs.jsbin.com/OxIDiVU/155/edit

收到序列化程序时修改json

App.ColorSerializer = DS.RESTSerializer.extend({
  extractArray: function(store, type, payload) {
    console.log(payload);
    payload.colors.forEach(function(color){
      color.links.items += "?foo=bar";
    });
    return this._super(store, type, payload);     
  }
});

示例:http://emberjs.jsbin.com/OxIDiVU/156/edit

修改适配器中的请求以在某些情况下包含额外信息

App.ColorAdapter= DS.RESTAdapter.extend({
    findHasMany: function(store, record, url) {
    var host = Em.get(this, 'host'),
        id   = Em.get(record, 'id'),
        type = record.constructor.typeKey;

    if (host && url.charAt(0) === '/' && url.charAt(1) !== '/') {
      url = host + url;
    }
    // check if post comments
    var builtUrl = this.buildURL(type, id),
        withPrefix = this.urlPrefix(url, builtUrl),
        data = {from:'foo'};
      return this.ajax(withPrefix, 'GET',{data:data});
  },
});

示例:http://emberjs.jsbin.com/OxIDiVU/154/edit

答案 1 :(得分:3)

我写了一个插件来完成此任务:https://github.com/mdehoog/ember-data-has-many-query

安装和配置后,您应该能够查询:

post.query('comments', { from: '2014-01-01', to: '2014-01-07' });

答案 2 :(得分:1)

我必须解决这个问题。我无法找到一个干净的解决方案,看着Ember Data的源代码,我无法想象更好的东西。也许这会帮助别人。

给定这样的关系以及需要传递查询参数来告诉API需要返回哪些注释(例如,您需要包含一个'搜索' param或' pageNumber' /' pageSize' for pagination)。

App.Post = DS.Model.extend({
  comments: DS.hasMany('comment', {async:true})
});

我添加了一个密钥' params'到hasMany属性的options对象。该值告诉适配器其他模型属性包含与该hasMany关系相关的参数。 (请注意,'对象'不是默认的EmberData属性类型,请参阅this gist以添加该类型。)

App.Post = DS.Model.extend({
  comments: DS.hasMany('comment', {async:true, params: 'comment_params'}),
  comment_params: DS.attr('object'),
});

修改模型以提供查询参数,我们需要使用适配器来使用信息:

App.ApplicationAdapter = DS.RESTAdapter.extend({
  findHasMany: function(store, snapshot, url, relationship) {
    var id   = snapshot.id;
    var type = snapshot.typeKey;

    url = this.urlPrefix(url, this.buildURL(type, id));

    if ('params' in relationship.options) {
      var params = snapshot.attr(relationship.options.params);
      if (params && Em.keys(params).length) {
        var queryParams = [];
        _.forEach(params, function (value, key) {
          queryParams.push(
            '%@=%@'.fmt(encodeURIComponent(key), encodeURIComponent(value))
          );
        });
        url = url + '?' + queryParams.join('&');
      }
    }

    return this.ajax(url, 'GET');
  },
});

现在,您可以在控制器中使用路径/控制器或观察器中的操作来修改params属性,然后在hasMany属性上调用get()或reload():

  // some controller ...
  // assume a template with binding to 'query'
  queryDidChange: function() {
    var model = this.get('model');
    var params = model.getWithDefault('comment_params', {});

    var value = this.get('query').trim();
    if (value !== '') {
      params['search'] = value;
    } else {
      delete params['search'];
    }
    model.set('comment_params', params);
    // calling reload to get a new set of comments
    // if comments have not been loaded yet only the 'get' is
    // necessary.
    model.get('comments').reload();
  }.observes('query'),

编辑: 我真的希望我不需要添加所有这些代码,但似乎返回hasMany的所有记录是默认的,没有开箱即用的方法来改变它。

编辑#2:我使用' _。forEach'来自lodash。你也可以使用

Object.keys(params).forEach($same_foreach_function_as_above)