如果用户点击li
条目,则会触发useThisAddress
操作,该操作会将isSelected
对象中的address
设置为true
。从那里bind-attr
负责设置适当的类(即`border-black')。
这是正确的方法吗?或者有更好的方法吗?
下面的代码有效。但是,我对在isSelected
对象上设置true
到address
有点不确定,因为它不是address
对象模型中的真实属性。
// Controller
import Ember from 'ember';
export default Ember.Controller.extend({
active: null,
actions: {
useThisAddress: function(address) {
address.set('isSelected', true);
var active = this.get('active');
if (active) {
active.set('isSelected', false);
}
this.set('active', address);
}
}
})
// Template
<ul>
{{#each address in model}}
<li {{bind-attr class='address.isSelected:border-black'}} {{action 'useThisAddress' address}}>
Address: {{address.address1}} {{address.address2}}, {{address.city}}, {{address.postalCode}}
</li>
{{/each}}
</ul>
答案 0 :(得分:2)
根据建议here,您只需在控制器中存储一个包含所选项目的单独列表。
答案 1 :(得分:1)
当你说它不是你对象模型的真实属性时,我假设你只是意味着它没有被持久存在。如果是这种情况,并且除了当前显示之外的任何地方没有其他用途,那么长期解决方案是使用组件。请参阅:http://jsbin.com/colacu/1
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return [Ember.Object.create({
address1: 'add1',
address2: 'add2',
city: 'Washington'
}),
Ember.Object.create({
address1: 'add1 again',
address2: 'add2 again',
city: 'Seattle'
})];
}
});
App.IndexController = Ember.Controller.extend({
active: null,
actions: {
useThisAddress: function(address) {
address.set('isSelected', true);
this.set('active', address);
}
}
});
App.XAddressComponent = Ember.Component.extend({
isSelected: false,
address: null,
tagName: 'li',
classNameBindings: ['isSelected'],
click: function() {
console.log('clicked!');
this.sendAction('action', this);
}
});
模板:
<script type="text/x-handlebars" data-template-name="index">
Selected: {{selected.value}}
<ul>
{{#each model as |item|}}
{{x-foo value=item action="select"}}
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="components/x-foo">
{{value}}
</script>
但你所拥有的应该没问题。
答案 2 :(得分:1)
我认为您的直觉反应是正确的 - 您不应该在模型上设置与您的UI严格相关的属性。
组件是Ember中用于存储UI层状态的构建块。在Ember这是一个有点棘手的时间,因为控制器也用于此目的,但他们正在走出困境。很快它将成为所有组件。
当我遇到像你这样的案例(list-with-selected-items)时,我通常会创建一个list
组件和一个list-item
组件。 list
知道选择了哪个项目,并且每个list-item
都知道它是否已被选中。对于您的简单情况,其他解决方案之一可能更直接,但我通常会发现这些列表,您最终会想要更多功能(绑定到选定项目,更复杂的模板等)。
因此,一种方法可能如下所示:
{{#address-list selected=selectedAddress as |list|}}
{{#each address in model}}
{{#address-list-item item=address list=list}}
<p>{{address.address1}}</p>
{{/address-list-item}}
{{/each}}
{{/address-list}}
您使用块参数(注意:需要Ember 1.10或更高版本)将<address-list>
传递到每个<address-list-item>
。现在,您的地址列表项可以通过向其发送操作来告诉列表已选择新地址:
App.AddressListItemComponent = Ember.Component.extend({
classNameBindings: ['active'],
active: function() {
return this.get('list.selected') === this.get('item');
}.property('list.selected', 'item'),
click: function() {
this.get('list').send('select', this.get('item'));
}
});
App.AddressListComponent = Ember.Component.extend({
actions: {
select: function(item) {
this.set('selected', item);
}
}
});
这会为您设置所有绑定,将.active
类添加到每个<address-list-item>
,并允许您从模板外部绑定到<address-list>
所选项目
现在,将list
定位为使用.send
是很尴尬的,这正是为什么我们很快就可以将操作传递给子组件(请查看{{3指导和搜索&#34;改进行动&#34;)。一旦该功能出现,您就可以将select
动作处理程序从<address-list>
直接传递到每个<address-list-item>
。但是现在这是一种方法,当这些变化落地时,它会使重构变得非常简单。
答案 3 :(得分:0)
自己学习Ember,但......我的.02。
列表方法是必须非Emberlike IMO。
假设您希望isSelected是准持久的,那么您的方式应该没问题。只要物体停留,它就会停留 - 甚至可能在路线变化之间(取决于你的型号)。
如果它应该更加短暂。将地址扔到组件中并将isChecked存储在组件控制器中。