使用带有 select 标记的 Marionette CompositeView 时获取 selected 选项
Getting the selected option when using Marionette CompositeView with select tag
我正在使用 CompositeView 来显示 select 标记,并且正在使用 CompositeView 的集合呈现选项。
OptionView = Marionette.ItemView.extend({
template: ...
tagName: "option",
}
});
SelectView = Marionette.CompositeView.extend({
template: ...
childView: OptionView,
childViewContainer: "select",
triggers: {
"change @ui.select": "do:something"
},
ui:{
select: "[ui-select]"
},
});
奇怪的是,当我尝试从包含 SelectView 的 LayoutView 中获取 selected 选项时,出现了不一致的行为:
EditActivities.LayoutView = Marionette.LayoutView.extend({
template: ...
regions: ...
onChildviewDoSomething: function(view){
console.log(view.ui.select.val());
}
})
当我在浏览器上更改 select 标签的值时,有时记录到控制台的是选项标签的内部 HTML,有时它会记录值。这是我的 OptionView 模板的样子:
<option value="<%=id%>"><%= name %></option>
我对不一致的行为感到有点难过。想法?
我明白了。问题出在我指定的 tagName 是 "option" 的 OptionView 中。在模板中,我还有选项标签,它实际上创建了一组嵌套的选项标签。这就是导致不可预测行为的原因。
我更改了它,所以我的模板现在只是:
<%= name %>
我现在遇到的问题是如何设置选项标签的值属性,因为现在它会为每个项目生成没有值的选项标签。我目前的解决方法是在视图上添加一个初始化函数,如下所示:
initialize : function (options) {
this.$el.attr("value",this.model.attributes.id);
}
但如果有更好的方法,我绝对乐于接受...
要将选项的值属性与 innerHTML 一起包含而不必诉诸于初始化中的修改,您可以像这样使用 Backbone 的属性散列:
SelectView = Marionette.CompositeView.extend({
tagName: 'option',
template: _.template('<%= name %>'),
attributes: function() {
return {
'value': this.model.id
};
}
});
正如 BaskingShark 提到的,属性散列可用于指定选项元素的属性。
项目视图可用于选项元素。
var OptionView = Marionette.ItemView.extend({
tagName: 'option',
attributes: function () {
return {
'value': this.model.get('id')
}
},
template: _.template('<%= name %>')
});
使用项目视图的集合视图可用于 select 标签。
var SelectOptionsView = Marionette.CollectionView.extend({
childView: OptionView
});
集合视图可以在布局视图的区域内呈现,其中也可以监听 select 标签上的事件。
Fiddle 例如:http://jsfiddle.net/95g1ojwk/3/
var pills = new Backbone.Collection([{
id: '',
name: 'Choose'
}, {
id: 'illusion',
name: 'Blue'
}, {
id: 'reality',
name: 'Red'
}]);
var OptionView = Marionette.ItemView.extend({
tagName: 'option',
attributes: function () {
return {
'value': this.model.get('id')
}
},
template: _.template('<%= name %>')
});
var SelectOptionsView = Marionette.CollectionView.extend({
childView: OptionView
});
var MyLayoutView = Mn.LayoutView.extend({
ui: {
destiny: "#destiny",
choice: '#choice'
},
regions: {
"options": "#options-region",
},
events: {
'change @ui.choice': 'chosenDestiny'
},
onRender: function () {
this.showChildView('options', new SelectOptionsView({
collection: pills,
el: this.ui.choice
}));
},
chosenDestiny: function (event) {
if($(event.target).val()==='reality'){
this.ui.destiny.text('Nothing but Truth!');
} else if($(event.target).val()==='illusion'){
this.ui.destiny.text('The Story Ends!');
} else {
this.ui.destiny.text('This is your last chance!');
}
}
});
new MyLayoutView({
el: '#app',
template: '#layout-template'
}).render();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<script src="http://marionettejs.com/downloads/backbone.marionette.js"></script>
<script type="text/template" id="layout-template">
<div id="options-region">
<select id="choice"></select>
</div >
<label id = "destiny" > </label>
</script>
<script type="text/template" id="image-template">
<div class = "sizer" > <img src = "http://placehold.it/<%= width %>x<%= height %>" /> </div>
</script>
<div id="app"></div>
我正在使用 CompositeView 来显示 select 标记,并且正在使用 CompositeView 的集合呈现选项。
OptionView = Marionette.ItemView.extend({
template: ...
tagName: "option",
}
});
SelectView = Marionette.CompositeView.extend({
template: ...
childView: OptionView,
childViewContainer: "select",
triggers: {
"change @ui.select": "do:something"
},
ui:{
select: "[ui-select]"
},
});
奇怪的是,当我尝试从包含 SelectView 的 LayoutView 中获取 selected 选项时,出现了不一致的行为:
EditActivities.LayoutView = Marionette.LayoutView.extend({
template: ...
regions: ...
onChildviewDoSomething: function(view){
console.log(view.ui.select.val());
}
})
当我在浏览器上更改 select 标签的值时,有时记录到控制台的是选项标签的内部 HTML,有时它会记录值。这是我的 OptionView 模板的样子:
<option value="<%=id%>"><%= name %></option>
我对不一致的行为感到有点难过。想法?
我明白了。问题出在我指定的 tagName 是 "option" 的 OptionView 中。在模板中,我还有选项标签,它实际上创建了一组嵌套的选项标签。这就是导致不可预测行为的原因。
我更改了它,所以我的模板现在只是:
<%= name %>
我现在遇到的问题是如何设置选项标签的值属性,因为现在它会为每个项目生成没有值的选项标签。我目前的解决方法是在视图上添加一个初始化函数,如下所示:
initialize : function (options) {
this.$el.attr("value",this.model.attributes.id);
}
但如果有更好的方法,我绝对乐于接受...
要将选项的值属性与 innerHTML 一起包含而不必诉诸于初始化中的修改,您可以像这样使用 Backbone 的属性散列:
SelectView = Marionette.CompositeView.extend({
tagName: 'option',
template: _.template('<%= name %>'),
attributes: function() {
return {
'value': this.model.id
};
}
});
正如 BaskingShark 提到的,属性散列可用于指定选项元素的属性。 项目视图可用于选项元素。
var OptionView = Marionette.ItemView.extend({
tagName: 'option',
attributes: function () {
return {
'value': this.model.get('id')
}
},
template: _.template('<%= name %>')
});
使用项目视图的集合视图可用于 select 标签。
var SelectOptionsView = Marionette.CollectionView.extend({
childView: OptionView
});
集合视图可以在布局视图的区域内呈现,其中也可以监听 select 标签上的事件。 Fiddle 例如:http://jsfiddle.net/95g1ojwk/3/
var pills = new Backbone.Collection([{
id: '',
name: 'Choose'
}, {
id: 'illusion',
name: 'Blue'
}, {
id: 'reality',
name: 'Red'
}]);
var OptionView = Marionette.ItemView.extend({
tagName: 'option',
attributes: function () {
return {
'value': this.model.get('id')
}
},
template: _.template('<%= name %>')
});
var SelectOptionsView = Marionette.CollectionView.extend({
childView: OptionView
});
var MyLayoutView = Mn.LayoutView.extend({
ui: {
destiny: "#destiny",
choice: '#choice'
},
regions: {
"options": "#options-region",
},
events: {
'change @ui.choice': 'chosenDestiny'
},
onRender: function () {
this.showChildView('options', new SelectOptionsView({
collection: pills,
el: this.ui.choice
}));
},
chosenDestiny: function (event) {
if($(event.target).val()==='reality'){
this.ui.destiny.text('Nothing but Truth!');
} else if($(event.target).val()==='illusion'){
this.ui.destiny.text('The Story Ends!');
} else {
this.ui.destiny.text('This is your last chance!');
}
}
});
new MyLayoutView({
el: '#app',
template: '#layout-template'
}).render();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<script src="http://marionettejs.com/downloads/backbone.marionette.js"></script>
<script type="text/template" id="layout-template">
<div id="options-region">
<select id="choice"></select>
</div >
<label id = "destiny" > </label>
</script>
<script type="text/template" id="image-template">
<div class = "sizer" > <img src = "http://placehold.it/<%= width %>x<%= height %>" /> </div>
</script>
<div id="app"></div>