Ember服务器端分页

时间:2014-04-01 15:41:35

标签: ember.js ember-data

尝试在视图中提供分页。

我的API一次返回500条记录,如果还有更多,我想自动加载它们。

虽然我现在的解决方案确实提出了要求,但我认为这不是最佳方式,但确实有效。

App.StructureAdapter = App.ApplicationAdapter.extend({
  findHasMany: function(store, record, url) {
    // based on the normal `findHasMany` code
    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;
    }

    return this.findWithURL(this.urlPrefix(url, this.buildURL(type, id)), 1);
  },
  findWithURL: function(url, page) {
    var that = this;
    var completeUrl = url + "?page=" + page;
    var nextPage = page + 1;
    return this.ajax(completeUrl, 'GET').then(function(data) {
      Em.Logger.log("calling then");
      if (data.structures.length > 0){
        that.findWithURL(url, nextPage);
      }
      return data;
    });
  }
});

我的问题是:

  • 是否有更好的方法可以自动获取给定请求的所有页面?
  • 如何正确确保建立关系。我的Structure对象上有父/子关系,但实际上只有第一页结果正确关联。

更新

以下是我的json响应:

{
    "structures": [
        {
            "id": 6536,
            "name": "Building",
            "updated_at": "2013-05-21T07:14:54-06:00",
            "person_id": 6535,
            "notes": ""
        },
        ... 499 more objects ...
    ]
}

它工作正常,它加载第一组就好了。如果需要,我可以使用extract / normalize方法对其进行调整。

这是我现在的normalize方法:

App.StructureSerializer = App.ApplicationSerializer.extend({
  normalize: function(type, hash, prop) {
    // adds the properly link to get children
    hash.links = { "children": "structures" };

    // change structure_id to parent_id
    hash.parent_id = hash.structure_id;
    delete hash.structure_id;

    return this._super(type, hash, prop);
  },
});

同样,链接使它自动知道在哪里寻找有很多关系。

仔细观察,虽然实际上已经调用了分页页面,但它们根本没有加载到Ember数据中。所以也许如果他们确实加载了,那么关系就会正确构建。

2 个答案:

答案 0 :(得分:2)

这是我最好的主意,我不知道它有多好用,你可能需要稍微玩一下。

StructureRoute中,继续正常返回模型,所以:

App.StructureRoute = Ember.Route.extend({
    model:function() {
        return this.store.find('structure');
    }
});

获取前500个对象并开始路由转换。

然后在StructureController中,使用如下查询参数获取其他模型:

App.StructureController = Ember.ArrayController.extend({
    init:function() {
        this.loadNextPage(2);
        this._super();  // this may not be necessary still, but the docs call for it
    },
    loadNextPage: function(page) {
        var self = this;
        var promise = this.store.find('structure',{page:page});

        promise.then(function(structures) {
            if(structures.get('length') < 500) { 
                self.loadNextPage(page + 1);
            }
        });
    }
});

因此当StructureController启动时,它会调用递归函数loadNextPage。这将一直运行,直到它击中包含少于500个模型的页面。希望,这将是最后一页。通过providing the second parameter to find,Ember应该向/structure?page=2触发请求。相反,如果您不介意加载时间较慢,您可以在路线中完成所有这些操作。

如果可能的话,我建议修改您的API,为您的请求添加一些分页元数据。然后,您可以使用该元数据来控制何时停止递归函数。您可以看到how to handle metadata here

最后,我不确定你的json中是否存在拼写错误,但你可能需要override your pluralization

Anywho,希望有帮助,而且我并不过分简单地解决这个问题!

答案 1 :(得分:1)

我真的不喜欢这个解决方案,但这确实工作。如果你有更清洁的方法,请发帖。

步骤1:将数据加载到灰烬数据

由于数据没有被加载到其他页面的Ember Data中,我不得不手动加载它。我通过调整上面创建的findWithURL函数来做到这一点。

findWithURL: function(url, page) {
  var that = this;
  var completeUrl = url + "?page=" + page;
  var nextPage = page + 1;
  var store = EditUserApp.__container__.lookup('store:main');
  return this.ajax(completeUrl, 'GET').then(function(data) {
    if (data.structures.length > 0){
      that.findWithURL(url, nextPage);
    }
    store.pushPayload('structure', data);
    return data;
  });
},

我觉得应该有更清洁的方法来做到这一点,但它确实有效。

第2步:重建关系

出于某种原因,它似乎没有重建孩子/父母的关系。为了解决这个问题,我必须使用didLoad模型中的Structure回调。

didLoad: function() {
  var parent = this.get('parent');
  if (parent) {
    var that = this;
    parent.get('children').then(function(children) {
      children.addObject(that);
    });
  }
},

欢迎任何有关如何改进此解决方案的建议。理想情况下,我觉得应该有一个更好的Ember方式来处理整个场景。