升级到Ember 2.0时删除itemController

时间:2015-12-08 11:14:56

标签: ember.js

我正在重写我的应用程序以符合Ember 2,并且在尝试重构ItemController时遇到了一个大问题。

目前我有一个arrayController,它有一个项目数组。用户有许多选项可用于对可显示的数据进行排序。 某些排序直接依赖于控制器上设置的属性(由用户通过模板提供)。为此,我目前声明一个项目控制器,这意味着我可以创建一个计算属性来计算我需要的排序值。这不能通过模型​​上的computedProperty来完成,因为模型不知道已设置的控制器属性。

如何重构这个不使用itemControllers - 我不知所措。

我已经将一些代码片段放在一起试图解释我的意思。我正在尝试对itemController属性numberOfSelectedFruit进行排序,其中每个人的值为#39;将取决于控制器上的selectedFruit属性(从模板中选取)。这是一个愚蠢的例子,但我认为它说明了这个问题。

我真的很感激这里有什么帮助,这是什么样的余烬2(我无法看到组件如何帮助)

// model
APP.Person = DS.Model.extend({
  name: DS.attr('string'),
  // Not proper code, but to show the structure of the fruit field
  fruit: [{type: DS.attr(‘string’), number: DS.attr(‘number’}]
})

// person_controller
APP.PersonItemController = Ember.ObjectController.extend({
  numberOfSelectedFruit: function() {
    var parentController = this.get('parentController');

    var fruitType = parentController.selectedFruit;
    var numberOfFruit = 0;
    this.get(‘fruit’).forEach(function(aFruit) {
      if(aFruit.type === fruitType) {
        numberOfFruit++;
      }
    });
    return numberOfFruit;
  }
})

APP.PersonController = Ember.ArrayController.extend({
  itemController: 'PersonItem',
  sortingOn: 'name',
  selectedFruit: 'orange',
  sortedPeople: Ember.computed.sort('filteredContent', 'sortingOn'),

})

编辑以添加模板代码

模板代码可以是以下简单的东西,使用选择器来选择水果' (这会在控制器上设置selectedFruit属性。

// person.hbs
<table>
  <tbody>
      {{#each sortedPeople as |person|}}
      <tr>
        <td>{{person.name}} {person.numberOfSelectedFruit}</td>
      </tr>
      {{/each}}
  </tbody>

</table>

2 个答案:

答案 0 :(得分:1)

如前所述,通常您可以使用组件作为项目控制器。这是非常简单明了的,大多数人比itemControllers更容易理解:

// person.hbs
<table>
  <tbody>
      {{#each sortedPeople as |person|}}
           {{person-item person=person selectedFruit=selectedFruit}}
      {{/each}}
  </tbody>

</table>

// components/person-item.js
import Ember from "ember";

const { computed } = Ember;

export default Ember.Component.extend({
    tagName: 'tr',

    numberOfSelectedFruit: computed('selectedFruit', 'person.fruit.@each.{type,number}', function() {
        const selectedFruit = this.get('selectedFruit');
        return this.get('person.fruit')
            .filter(aFruit => aFruit.type === selectedFruit)
            .map(aFruit => aFruit.number)
            .reduce((previous, current) => previous + current);
    })
});

// templates/components/person-item.hbs

<td>{{person.name}} {{numberOfSelectedFruit}}</td>

但是,您说您希望能够通过numberOfSelectedFruit对人进行排序。由于您不再拥有itemController,ObjectController或ArrayController,您必须将numberOfSelectedFruit计算属性移动到ObjectProxy,如下所示:

// controllers/person.js
import Ember from "ember";
import PersonProxy from "../models/person-proxy";

export default Ember.Controller.extend({
    // ...

    proxiedPeople: computed('model.[]', function() {
        return this.get('model').map((person) => PersonProxy.create({
            content: person,
            context: this
        }));
    }),

    selectedFruit: 'orange'
    sortedPeople: computed.sort('proxiedPeople', 'sortingOn'),
    sortingOn: ['numberOfSelectedFruit:asc']
});

// models/person-proxy.js
import Ember from "ember";

const { computed } = Ember;

export default Ember.ObjectProxy.create({
    selectedFruit: computed.readOnly('context.selectedFruit')

    numberOfSelectedFruit: computed('selectedFruit', 'fruit.@each.{type,number}', function() {
        const selectedFruit = this.get('selectedFruit');
        return this.get('fruit')
            .filter(aFruit => aFruit.type === selectedFruit)
            .map(aFruit => aFruit.number)
            .reduce((previous, current) => previous + current);
    })
});

ObjectProxy是itemController在Ember 1.x中的基础。有关ObjectProxy的工作原理,请参阅http://emberjs.com/api/classes/Ember.ObjectProxy.html。 希望这会有所帮助。

答案 1 :(得分:0)

要在没有itemController的情况下执行此操作,您需要定义一个组件(在您的情况下可能称为person-item)。有效的组件只是一个控制器 - 模板对,在概念上从其他所有东西中抽象出来。在名为person的组件上定义属性,并在{{each}}循环内将模型分配给它。

此时,person-item.js文件(组件逻辑)现在是以前的项目控制器,现在它有自己的模板(person-item.hbs)。

所以代码是相同的(相当多),但模板现在位于一个单独的文件中。