【问题标题】:Ember server side paginationEmber 服务器端分页
【发布时间】:2014-04-01 15:41:34
【问题描述】:

试图在视图本身内提供分页。

我的 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 方法中进行调整。

这是我现在的标准化方法:

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 数据中。因此,也许如果他们确实加载了,那么关系就会正确建立。

【问题讨论】:

  • 你能发布你从服务器收到的json响应吗?你的模型是什么样的?
  • 你好@NicholasJohn16,我刚刚添加了 JSON 响应。
  • 你在使用ember-data吗?
  • 是的,我正在使用 Ember 数据。
  • @RyanJM 我最近也做了一些关于祖先/自加入关系的工作。我没有发现我必须使用 normalize 函数;所以我不确定我的示例应用程序是否对您有帮助,或者您是否使用了我没有想到的更好的方法。这是链接以防万一:github.com/brandonjmckay/ember-ancestry-example

标签: ember.js ember-data


【解决方案1】:

这是我的最佳想法,我不知道它的效果如何,您可能需要尝试一下。

在您的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

任何人,希望对您有所帮助,我并没有过于简单地解决问题!

【讨论】:

  • 尼古拉斯,感谢您的回答。不知道为什么我没有早点看到它。我必须尝试一下,但我认为这会比我尝试的要好得多。 :)
  • 看起来这与我的问题相同。我不是在做一个 Array 控制器,而是在做一个 ObjectController,然后循环遍历孩子。执行此查找时,子关系不会更新。 github.com/emberjs/data/issues/1864
  • 如果你代表多个模型,你应该使用 ArrayController。为什么要使用 ObjectController?
  • 我正在展示一个树形结构。父级(ObjectController)循环遍历子级(每个子级都有自己的 ObjectController)。我需要一个 ObjectController,以便我可以根据用户正在使用的特定结构提供功能。
  • 感谢尼古拉斯的帮助。这让我得到了一个更清洁的解决方案。我现在可以手动添加对象,直到 Ember Data 得到修复。
【解决方案2】:

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

第 1 步:将数据加载到 Ember 数据中

由于其他页面的数据没有加载到 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 步:重建关系

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 2023-03-12
    • 2020-03-13
    相关资源
    最近更新 更多