鉴于我有一个问题列表,在一个模型中使用控件类型(即文本框,选择列表,复选框等),该模型是通过asmx web方法检索的JSON中使用ko.mapping
构建的,如何根据多个DOM元素设置问题的答案?
说我有以下问题:
{
text:"This is the question text",
answer:null,
controlType:"picker"
}
然后我创建了一个picker
模板,如下所示:
<select data-bind="options: ['Large','Medium','Small'], optionsCaption: 'Select size...'" />
<select data-bind="options: ['Black','Red','Green'], optionsCaption: 'Select colour...'" />
当两个SELECT元素都选择了值时,我需要将answer
设置为这个问题。
我还需要保留答案,所以如果question
从服务器返回并填充了答案(保存表单提交等),则在SELECT元素中选择相应的值,即:
{
text:"This is the question text",
answer:"Large Red",
controlType:"picker"
}
这将为我选择元素中的[Large]和[Red]。
这是我到目前为止所尝试的内容。
ko.computed
编辑:这是一个working jsFiddle for this想法。
我已经在我的视图模型中回答问题,并在每个问题上设置ko.computed
,通过ID访问DOM,因此我的模板变为:
<select data-bind="attr: { 'id':'leftOption' }, options: ['Large','Medium','Small'], optionsCaption: 'Select size...'" />
<select data-bind="attr: { 'id':'rightOption' }, options: ['Black','Red','Green'], optionsCaption: 'Select colour...'" />
我的计算值变为:
question.computedAnswer = ko.computed({
read: function () {
return question.answer();
},
write: function (value) {
var left = $('#leftOption').val();
var right = $('#rightOption').val();
question.answer(left + ' ' + right);
}
});
这只是尖叫哦,上帝,拜托,不!不过!对我来说,因为我正在以非常混乱的方式访问DOM(并且最近学会了一个很好的做法,就是不要像这样访问DOM ,感觉各种错误!!)。
警告:我仍然要掌握自定义处理程序
为了通过绑定处理程序限制对DOM的访问,我为此创建了一个...但似乎无法让它工作。这个想法出现在provided jsFiddle中,但它并没有起作用,因为它没有做任何事情!
基本上我正在尝试在处理程序中执行此操作:
ko.bindingHandlers.computedAnswer = {
update: function (element, value, all, model, context) {
switch (model.controlType()) {
case 'picker': {
var $parent = $(element).parent();
var first = $parent.find('select:first').val();
var second = $parent.find('select:last').val();
if (first && second) {
model.answer(first + ' ' + second);
} else {
model.answer(null);
}
}
}
}
};
并尝试在我的模板上激活它,如下所示:
<select data-bind="computedAnswer: $data, options: ['Large','Medium','Small'], optionsCaption: 'Select size...'" />
<select data-bind="computedAnswer: $data, options: ['Black','Red','Green'], optionsCaption: 'Select colour...'" />
有没有人知道如何让这个工作?
答案 0 :(得分:1)
视图是存储数据的错误位置。它也不是很灵活。如果您的picker
个问题存储了自己的选项怎么办?这不仅会让每个问题都有不同的选项,而且会有不同的数字选项。
它还保存视图的数据,并简化您的HTML和viewmodel代码,并保持DOM访问不受视图模型的影响,而无需自定义绑定(不应该避免自定义绑定所有的费用,我只是觉得这不是他们的好例子。)
A picker
问题
}, {
text: "dependent on master question",
answer: null,
controlType: "picker",
pickers: [
{ name: "Size", options: ['Large', 'Medium', 'Small'], value: '' },
{ name: "Color", options: ['Red', 'Blue', 'Green'], value: '' }
]
}
查看强>
<script type="text/html" id="picker">
<!-- ko foreach: pickers -->
<label data-bind="text: name"></label>
<select data-bind="options: options, value: value, optionsCaption: 'Choose...'"></select>
<!-- /ko -->
</script>
计算出的答案
viewModel.questions().forEach(function (question) {
if (question.controlType() === 'picker') {
question.answer = ko.computed(function() {
var answers = [];
question.pickers().forEach(function(i) {
if (i.value())
answers.push(i.value());
});
return answers.length === question.pickers().length ?
answers.join(' ') : '';
});
}
});