【问题标题】:How to filter a local hasMany record set in Ember.js如何过滤 Ember.js 中的本地 hasMany 记录集
【发布时间】:2015-07-22 21:51:15
【问题描述】:

在过滤 hasMany 对象的 ul 时,我在进行 dom 更新时遇到问题。这是我想要完成的任务:

当用户点击其中一个链接时,它应该过滤掉包含相应元素的 div。这是我当前的代码:


路线

import Ember from 'ember';
import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';

export default Ember.Route.extend(AuthenticatedRouteMixin,{
  model: function (params) {
    return this.store.find('recipient', params.recipient_id);
  },

  setupController: function (controller, model) {
    this._super(controller, model);
    var categories = model.get('offers').map(function(offer){
      var category = Ember.Object.create();
      category.name = offer.get('company_industry');
      category.count = model.get('offers').filterBy('company_industry', offer.get('company_industry')).get('length');
      return category;
    });

    controller.set('categories', categories);
  }

});

这会将categories 设置为一个 Ember 对象,如下所示: {name: 'Home And Beauty', count: 1}

组件:filterable-offers.js

import Ember from 'ember';

export default Ember.Component.extend({

  actions: {
    filter: function(categoryName) {
      return this.get('model').get('offers').filterBy("company_industry", categoryName);
    }
  }

});

filterable-offers.hbs

<ul>
  {{#each categories as |category|}}
      <li>
        <a {{action "filter" category.name}}>{{category.name}} ({{category.count}})</a>
      </li>
  {{/each}}
</ul>

recipient.hbs

  <div class="row">
  <div class="col-sm-4">
    {{filterable-offers categories=categories model=model}}
  </div>
  <div class="col-sm-8">
    {{#each model.offers as |offer|}}
      <div class="offer-card">
        {{offer.text}}
      </div>
    {{/each}}
  </div>

我知道我错过了一些简单的东西,比如在这里观察一些东西,但是当我点击链接过滤掉元素时,dom 中没有任何更新。过滤器函数确实返回了我想要的结果集,但主收件人模板中的 model.offers 调用没有观察到它。

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    您的问题是您正在从操作处理程序返回过滤后的结果。动作处理程序不使用返回值(大部分情况下)。相反,您需要将过滤后的项目放置在模板可以访问它们的地方。由于您的过滤器选择器位于不同的组件中,因此我会这样做(如果您对此有任何疑问,请询问):

    1. 在您的组件中,重新发送过滤器操作,使其冒泡到控制器:

      actions: {
          filter(categoryName) {
              this.sendAction('filterByCategory', categoryName);
          }
      }
      
    2. 确保您的控制器可以通过在模板中订阅它来接收操作:

      {{filterable-offers categories=categories filterByCategory='filterByCategory'}}
      
    3. 在您的控制器中为filterByCategory 操作添加一个处理程序:

      actions: {
          filterByCategory(categoryName) {
              // We'll use this in the next step
              this.set('filterCategory', categoryName);
          }
      }
      
    4. 设置一个计算属性,该属性将根据过滤器类别自动过滤您的项目。我们在控制器上有 filterCategory 属性,所以让我们使用它:

      filteredOffers: Ember.computed('model.offers.@each.company_industry', 'filterCategory', {
          get() {
              const offers = this.get('model.offers');
              const filterCategory = this.get('filterCategory');
      
              // If there's no category to filter by, return all of the offers
              if (filterCategory) {
                  return offers.filterBy('company_industry', filterCategory);
              } else {
                  return offers;
              }
          }
      })
      
    5. 最后,不要在模板中使用model.offers,而是使用filteredOffers

          {{#each filteredOffers as |offer|}} ... {{/each}}
      

    该答案可能比您想要的更深入一点,但希望它有所帮助。您遇到的主要问题是您需要某种方式来告诉您的控制器使用过滤后的一组优惠而不是原始组。这只是实现这一目标的众多方法之一。

    【讨论】:

    • 超级有用的答案。我有一个问题要问你。当 ember 2.0 到来并且控制器开始被弃用时,您的答案将如何改变?这个问题不需要花太多时间,因为你已经超出了我的预期,只是一个想法。
    • 我的答案不会改变。你仍然会做同样的事情。但不是将filterByCategory 操作放在控制器中,而是将其放在可路由组件中。代码将保持不变。
    • 你能解释一下get()函数调用在控制器内部的用途吗?
    • 这是 1.12 中引入的new computed property syntax。我还使用了很多 ES6 特性(因为 Ember CLI 默认包含 Babel),所以如果你看到一些你不认识的东西,也许可以再读一遍 ES6 特性集。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    相关资源
    最近更新 更多