如何突出显示所选地址?
How to highlight selected address?
如果用户单击 li
条目,它会触发 useThisAddress
操作,将 address
对象中的 isSelected
设置为 true
。从那里 bind-attr
负责设置适当的 class (即“border-black”)。
这是解决这个问题的正确方法吗?或者有更好的方法吗?
下面的代码有效。但是,我对在 address
对象上将 isSelected
设置为 true
有点不确定,因为它在 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>
按照建议here,您可以在控制器中存储一个包含所选项目的单独列表。
我自己正在学习 Ember,但是......我的 .02.
列表方法是必须的,Ember不像 IMO。
假设您希望 isSelected 是准持久性的,您这样做的方式应该没问题。只要对象停留,它就会一直停留——甚至可能在路线更改之间(取决于您的模型)。
如果它应该是更短暂的..将地址扔到一个组件中并将isChecked存储在组件控制器中。
当您说它在您的对象模型上不是真实的 属性 时,我假设您的意思只是它没有被持久化。如果是这种情况,并且除了当前显示之外,该标志在任何地方都没有其他用途,则长期解决方案将是使用一个组件。参见: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>
不过你有的应该没问题。
我认为你的直觉反应是正确的 - 你不应该在你的模型上设置与你的 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
class 添加到每个 <address-list-item>
,并让您绑定到 <address-list>
的所选项目在模板之外。
现在,像这样针对 list
使用 .send
很尴尬,这正是我们很快就能将操作向下传递到子组件的原因(查看 Road to Ember 2.0 指南并搜索 "Improving Actions")。一旦该功能落地,您将能够将 select
操作处理程序从 <address-list>
直接传递到每个 <address-list-item>
。但就目前而言,这是一种可行的方法,当这些更改落地时,它将使重构变得非常简单。
如果用户单击 li
条目,它会触发 useThisAddress
操作,将 address
对象中的 isSelected
设置为 true
。从那里 bind-attr
负责设置适当的 class (即“border-black”)。
这是解决这个问题的正确方法吗?或者有更好的方法吗?
下面的代码有效。但是,我对在 address
对象上将 isSelected
设置为 true
有点不确定,因为它在 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>
按照建议here,您可以在控制器中存储一个包含所选项目的单独列表。
我自己正在学习 Ember,但是......我的 .02.
列表方法是必须的,Ember不像 IMO。
假设您希望 isSelected 是准持久性的,您这样做的方式应该没问题。只要对象停留,它就会一直停留——甚至可能在路线更改之间(取决于您的模型)。
如果它应该是更短暂的..将地址扔到一个组件中并将isChecked存储在组件控制器中。
当您说它在您的对象模型上不是真实的 属性 时,我假设您的意思只是它没有被持久化。如果是这种情况,并且除了当前显示之外,该标志在任何地方都没有其他用途,则长期解决方案将是使用一个组件。参见: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>
不过你有的应该没问题。
我认为你的直觉反应是正确的 - 你不应该在你的模型上设置与你的 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
class 添加到每个 <address-list-item>
,并让您绑定到 <address-list>
的所选项目在模板之外。
现在,像这样针对 list
使用 .send
很尴尬,这正是我们很快就能将操作向下传递到子组件的原因(查看 Road to Ember 2.0 指南并搜索 "Improving Actions")。一旦该功能落地,您将能够将 select
操作处理程序从 <address-list>
直接传递到每个 <address-list-item>
。但就目前而言,这是一种可行的方法,当这些更改落地时,它将使重构变得非常简单。