【问题标题】:Ember.js sorting and filtering children of a hasMany relationship in parent routeEmber.js 排序和过滤父路由中 hasMany 关系的子级
【发布时间】:2013-01-30 09:57:27
【问题描述】:

更新 #2

我发现,当我将过滤逻辑重构为在 PostController 中的复合计算属性中而不是在单个路由中时,我能够使其正常工作。该解决方案最终依赖于由特定 #linkTo 路由操作设置的单个动态变量,该操作触发 PostController 计算属性中的过滤更改。我有很多工作要赶上,所以我现在不能发布这个特定问题的解决方案,但是当我可以的时候,我会在下面详细解释解决方案。现在,对于他在下面给出的部分但非常有用的指导,我已将@twinturbo 的答案标记为正确。再次感谢大佬!!非常感激!!

更新 #1

最新的小提琴是在http://jsfiddle.net/aZNRu/14/@twinturbo 的帮助下,在其 Post 父控制器中对 Comments 的“rank”属性进行排序,以及基本过滤。在过滤路线中并创建新评论时,仍然存在无法自动更新视图的问题。

原始问题

我看到了 there is talk of combining the sortable mixin with filtering functionality,但现在,正如您在我的 jsfiddle example 中看到的那样,我在排序和过滤方面都遇到了问题:

1) 我不知道如何按其父控制器中的特定子属性进行排序。如果我们有:

App.Post = DS.Model.extend({
    title: DS.attr('string'),
    post: DS.attr('string'),
    comments: DS.hasMany('App.Comment')
});

App.Comment = DS.Model.extend({
    post: DS.belongsTo('App.Post'),
    description: DS.attr('string'),
    isActive: DS.attr('boolean'),
    rank: DS.attr('number')
});

App.Router.map(function() {
  this.resource("posts", { path: "/" }, function() {
    this.resource('post', { path: ':post_id' }, function() {
        this.route('active');
        this.route('inactive');
     });
   });
});

我希望能够按每个帖子的“排名”属性按升序对每个帖子的 cmets 进行排序。我想做类似的事情:

App.PostController = Ember.ObjectController.extend({
    sortProperties: ['comments.rank']

但一方面,我认为 sortProperties 仅适用于 arrayControllers,而且我认为它的工作深度不能超过一层。我怎样才能做到这一点?

2) 第二个问题是在过滤路由时无法自动更新视图。例如,如果您查看 jsfiddle 并通过单击“Active Comments”进入活动过滤路由,您将获得对当前数据的良好过滤效果。但是,如果您保留在活动路线中并通过单击“添加新评论”创建一条处于活动状态的新记录,则该记录不会自动呈现在“活动”下,并且仅当您单击另一条路线然后返回该路线时才会出现。

我是在路由中设置路由过滤不正确还是在模板中引用错误?

App.PostActiveRoute = Ember.Route.extend({
  setupController: function() {
    var post = this.controllerFor('post').get('model'),
    comments = post.get('comments');

    var activeComments = comments.filter(function(comment) {
      if (comment.get('isActive')) { return true; }
    });

    this.controllerFor('post').set('filteredComments', activeComments);
  }
});


<ul>
    {{#each comment in filteredComments}}
        <li>{{comment.rank}} {{comment.description}} - isActive: {{comment.isActive}}</li>
    {{/each}}
</ul>

您可以就这些问题提供任何见解,我们将不胜感激!

【问题讨论】:

  • 已经有一段时间了,但是你有没有机会向我们展示你最后得到了什么? (这段代码还能继续工作吗?)

标签: ember.js ember-data ember-router


【解决方案1】:

但一方面,我认为 sortProperties 仅适用于 arrayControllers,而且我认为它的工作深度不能超过一层。我怎样才能做到这一点?

您是正确的,sortProperties 仅适用于 Ember.ArrayController

你真的不需要做任何花哨的事情来实现这一点。只需将 cmets 数组包装在包含可排序 mixin 的新 ArrayProxy 中。然后您可以对 cme​​ts 进行排序。那么你就不需要嵌套属性了,因为你正在对一个 cmets 数组进行排序。

请不要扩展DS.ManyArray。没有必要。

至于排序和过滤,这里需要用到合成。这意味着创建类似filteredContentsortedContent 的东西。然后你可以让sortedContent 使用filteredContent

更新:

PostController = Ember.ObjectController.extend({
  comments: (function() {
    return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
      sortProperties: ['rank'],
      content: this.get('content.comments')
    });
  }).property('content.comments')

【讨论】:

  • 您好 twinturbo,感谢您的回复! “将 cmets 数组包装在包含可排序 mixin 的新 ArrayProxy 中”是指从 PostController 或 PostRoute 中创建此 arrayProxy,还是定义绑定到 this.controllerFor('post ').get('cmets') 并将 #each cmets' 渲染上下文更改为新的 cmetsController?
  • 最简单的方法是覆盖ObjectController 上的comments 属性,因为它只是一个代理。查看我的更新回复。
  • 太棒了,非常感谢!一旦你知道了语法,那就太好了。您的代码中唯一的错误是没有做到这一点: return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, { 而不是 return ArrayProxy.createWithMixins(Ember.SortableMixin, { 。更新的小提琴位于 jsfiddle.net/aZNRu/12 。现在我需要采取通过单击路由使 cmets PostController arrayProxy 可过滤。非常感谢您的帮助!
  • 谢谢!很棒的反应!
  • 完美运行!在模板中,我们必须通过“controller.cmets”而不是“content.cmets”来访问排序后的 cmets,因为这对于像我这样的 Ember n00b 来说是这样的。
【解决方案2】:

这也可以通过计算属性宏来完成。

PostController = Ember.ObjectController.extend({
 commentSortProperties: ['rank:desc', 'createdAt:asc'],
 comments: Em.computed.sort('model.comments', 'commentSortProperties')
});

Take a look at the code here.

【讨论】:

  • 我认为应该是 'commentSortProperties' 而不是 commentSortProperties - 因为第二个版本不适合我。
  • 这在与本文所述相同的情况下对我有用。
【解决方案3】:

也许您可以通过扩展存储并在 createManyArray 方法中添加可排序的 mixin 来使您的多数组可排序? (我没有测试它是否有效)

App.store = DS.Store.create({
  createManyArray: function (type, clientIds) {
    var array = DS.ManyArray.create(Ember.SortableMixin, { type: type, content: clientIds, store: this });

    clientIds.forEach(function (clientId) {
        var recordArrays = this.recordArraysForClientId(clientId);
        recordArrays.add(array);
    }, this);

    return array;
  }
});

那么就可以绑定到array的arrayContent

{#each comment in filteredComments.arrangedContent}}

【讨论】:

  • 感谢您的回复!我尝试通过将其添加到 the fiddle example 的 App.Store 来实施此解决方案,但无法使其正常工作。顺便说一句,这似乎是一个非常常见的用例,我怀疑这可以通过将 cmets 移动到它们自己的 cmetsController 和 cmetsRou​​te,并通过需要或 controllerFor 设置控制器之间的关系来解决,但我尝试这样做有一切都没有结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-19
相关资源
最近更新 更多