我正在重写我的应用程序以符合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>
答案 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)。
所以代码是相同的(相当多),但模板现在位于一个单独的文件中。