Knockout.js 从多个DOM元素中设置ko.observable值

Knockout.js 从多个DOM元素中设置ko.observable值,knockout.js,Knockout.js,假设我有一个问题列表,在一个通过asmx web方法从JSON检索的ko.mapping构建的模型中有控件类型(即文本框、选择列表、复选框等),我如何根据多个DOM元素设置问题的答案 假设我有以下问题: { text:"This is the question text", answer:null, controlType:"picker" } 然后我创建了一个picker模板,如下所示: <select data-bind

假设我有一个问题列表,在一个通过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 data-bind="computedAnswer: $data, options: ['Large','Medium','Small'], optionsCaption: 'Select size...'" />
<select data-bind="computedAnswer: $data, options: ['Black','Red','Green'], optionsCaption: 'Select colour...'" />    
这将为我从元素中选择[Large]和[Red]

这是我到目前为止试过的

在我的可观察对象上设置一个
ko.computed
编辑:这里有一个想法

我在视图模型中循环了问题,并在每个问题上设置了一个
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的访问,我为此创建了一个绑定处理程序。。。但似乎无法让它工作。这个想法是在,但它不工作,因为它没有做任何事情

基本上,我正在处理程序中尝试这样做:

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="options: ['Large','Medium','Small'], optionsCaption: 'Select size...'" />
<select data-bind="options: ['Black','Red','Green'], optionsCaption: 'Select colour...'" />
<select data-bind="computedAnswer: $data, options: ['Large','Medium','Small'], optionsCaption: 'Select size...'" />
<select data-bind="computedAnswer: $data, options: ['Black','Red','Green'], optionsCaption: 'Select colour...'" />    


有人知道如何让它工作吗?

视图是存储数据的错误位置。它也不是很灵活。如果你的
选取者
问题存储了他们自己的选项怎么办?这不仅允许每个问题有不同的选项,而且允许有不同数量的选项

它还保留了视图的数据,简化了HTML和viewmodel代码,并且在不需要自定义绑定的情况下将DOM访问排除在viewmodel之外(并不是说您应该不惜一切代价避免自定义绑定,我只是认为这不是一个好的例子)

问题
选取者
问题

}, {
    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>

你的问题值得更多的投票。您总是有多个小提琴,显示问题和您认为应该采取的路径,您根据您遇到的具体问题定制它们(即使您过去的问题表明整个问题有更多的部分),您在问题中包含代码,并清楚地展示您的努力。@Tyrsius我很感激。我觉得这只是一种普通的礼貌,如果有人打算自己抽出时间来帮助你,那么你应该帮助自己才是公平的!这是一种礼貌,但肯定不常见。有趣的是,我从未想过在提问时会有一系列的挑选者。。。但是,如果我无法控制返回给我的JSON,并且我必须在模板中指定SELECT元素的数量,那该怎么办?嗯,我想我可以在使用pickers数组解析JSON之后扩展可观察的元素?我想这就是我要走的路,除非我(或其他人)想出一个更好的方法。如果你没有控制权,我会在解析它们之后扩展它们。因为无论哪种方式,viewmodel都应该表示数据,而不是视图。如果选项真的是静态的,你可以把它们放在根视图模型上,而不是每个问题上。很抱歉,最近接受了,对我的问题做了一些整理。