如何在应用程序中共享设置?

时间:2016-01-14 19:17:50

标签: ember.js

我有一个列出一些类别/子类别的主页面。只要单击子类别,就会触发操作openSubcategory

// routes/application.js

import Ember from 'ember';

export default Ember.Route.extend({
    userSelections: Ember.inject.service('user-selections'),

    actions: {
        openSubcategory: function(categoryId, subcategoryId) {
            var userSelections = this.get('userSelections');
            userSelections.set('category', categoryId);
            userSelections.set('subcategory', subcategoryId);
            this.transitionTo('filter-categories');
        },
    }
});

要将选择传递给相应的控制器,我正在使用服务:

// services/user-selections.js

import Ember from 'ember';

export default Ember.Service.extend({
    category: null,
    subcategory: null,
    init() {
        this._super(...arguments);
        this.set('category', null);
        this.set('subcategory', null);
    },
});

评估于:

// controllers/filter-categories.js

import Ember from 'ember';

export default Ember.Controller.extend({
    userSelections: Ember.inject.service('user-selections'),
    init() {
        this._super(...arguments);
        this.get('userSelections');  // We need to get it so that we can observe it?
        // We can not declare the observers, because we need to make sure userSelections is first read
        this.addObserver('userSelections.category', function() {
            Ember.run.once(this, 'refreshProducts');
        });
        this.addObserver('userSelections.subcategory', function() {
            Ember.run.once(this, 'refreshProducts');
        });
    },
    actions: {
        changedCategory: function(selectedCategory) {
            this.set('selectedCategory', selectedCategory);
            this.get('userSelections').set('category', selectedCategory.value);
        },
        changedSubcategory: function(selectedSubcategory) {
            this.set('selectedSubcategory', selectedSubcategory);
            this.get('userSelections').set('subcategory', selectedSubcategory.value);
        },
    },
    refreshProducts: function() {
        var userSelections = this.get('userSelections'),
            category = userSelections.get('category'),
            subcategory = userSelections.get('subcategory');
        var products = this.store.filter('product', function(product) {
            var catId = parseInt(product.get('category').get('id')),
                subcatId = parseInt(product.get('subcategory').get('id'));
            if (category && catId !== category) {
                return false;
            }
            if (subcategory && subcatId !== subcategory) {
                return false;
            }
            return true;
        });
        this.set('model', products);
    },
});

观察userSelections(在评论中看到的一些黑客攻击后)可以正常工作:这些操作正在触发refreshProducts方法。但似乎该方法在来自应用程序路由时未被触发,可能是因为controllers/filter-categories尚未初始化。

(*)根据documentation,观察服务有很多“问题”。

因此,代码需要以难以理解的方式编写。 路由/控制器之间共享数据的方式是否比使用服务更好?

修改

这些是我的模板:

// partials/categories.hbs (used on the application.hbs template)

{{#each model.categories as |category| }}
<div class="categories-list row">
  <div class="container">
    <h3 class="category-name centered">
      <span class="bg-left"></span>
      <span class="bg-center uppercase">{{category.name}}</span>
      <span class="bg-right"></span></h3>
  </div>
  <div class="category owl-carousel">
    {{#each category.subcategories as |subcategory| }}
    <div class="category-item">
      <a href="{{subcategory.link}}">
        <div class="category-icon">
          <img src="{{subcategory.image}}">
        </div>
        <h4 class="capitalize" {{action "openSubcategory" category.id subcategory.id}}>{{subcategory.name}}</h4>
      </a>
    </div>
    {{/each}}
  </div>
</div>
{{/each}}

// filter-categories.hbs

<div class="container">
  <div class="row">
    <div class="col-md-12">
      <h2>Our Vault</h2>
      <legend>Filter products by category / subcategory</legend>
    </div>
  </div>
  <div class="row">
    <div class="col-md-12">

      <form class="form-inline portfolio-form">
        <div class="form-group col-md-2">
          {{#power-select options=optionsCategory selected=selectedCategory onchange=(action "changedCategory") as |category|}}
            {{category.text}}
          {{/power-select}}
        </div>
        <div class="form-group col-md-2">
          {{#power-select options=optionsSubcategory selected=selectedSubcategory onchange=(action "changedSubcategory") as |subcategory|}}
            {{subcategory.text}}
          {{/power-select}}
        </div>
        <div class="form-group col-md-2">
            <button type="button" class="btn btn-default" {{action "clearSelections" id}}><i class="fa fa-remove"></i> Clear Filters</button>
        </div>
      </form>

    </div>
  </div>
  <div class="row">
    {{partial "products"}}
  </div>
</div>

1 个答案:

答案 0 :(得分:1)

您是否有理由避免使用dynamic segments?如果不是,您可以在使用transitionTo('filter-categories')时将类别和子类别作为动态细分传递,增加的好处是该路线将变为可链接:)

所以对于例如。你应该像这样定义你的filter-categories路线:

// router.js
...
this.route('filter-categories', { path: 'filter-categories/:category_id/:subcategory_id' });
...

现在,您可以在routes/filter-categories.js路由器中执行以下操作:

// routes/filter-categories
import Ember from 'ember';

export default Ember.Route.extend({
  model(params) {
    // you can put your `refreshProducts` logic in here
    // (I mean in this router not literally in this method)
    // and return the products model or whatever you want
    // I will just return an object with the ids for simplicity
    return {
      categoryId: params.category_id,
      subcategoryId: params.subcategory_id
    };
  }
...

现在在你的申请路线中:

// routes/application.js

import Ember from 'ember';

export default Ember.Route.extend({
    actions: {
        openSubcategory: function(categoryId, subcategoryId) {
            this.transitionTo('filter-categories', categoryId, subcategoryId);
        }
    }
});

编辑:

如果您不总是拥有categoryIdsubcategoryId,则可以使用query parameters代替动态细分。