0

示例 jsFiddle


这是我的 JSON 形式的模型结构的概述

var json = JSON.stringify([{
    text: 'Enter your name',
    controlType: 'TextBox',
    answer: null
}, {
    text: 'Choose some of these',
    controlType: 'Label',
    answer: null
}, {
    text: 'Item one',
    controlType: 'CheckBox',
    answer: null
}, {
    text: 'Item two',
    controlType: 'CheckBox',
    answer: null
}, {
    text: 'Item three',
    controlType: 'CheckBox',
    answer: null
}, {
    text: 'Choose from multiple elements',
    controlType: 'Multiple',
    answer: null
}, ]);

我有一个问题列表(上面详述),每个问题都有其各自textcontrolType属性。我创建了一个自定义绑定处理程序来在表单上绘制输入,并创建另一个处理程序来处理answer基于所创建控件的 DOM 结构的处理程序。

例如,对于一个特定的控件类型,我将Multiple作为一种类型,它将创建以下标记:

<select data-bind="options: ['Jan','Feb','Mar'...], optionsCaption: ' - '"></select>
<input type="text" size="5" />

这基本上允许用户在2013 年 1 月提交单个问题的答案,但我正在努力让绑定处理程序工作。

当我第一次开始这样做时,我使用计算的 observables 扩展了每个问题 - 所以在这种情况下,我将question使用以下计算扩展:

question.answer.month = ko.computed({
    read: function () {
        if (this.answer()) {
            return this.answer().split(' ')[0]; // returns the month part
        }
        return null;
    },
    write: function (value) {
        if (value) {
            this.answer(value);
        }
    },
    owner: question
});

但是我开始陷入各种循环引用地狱——所以我想我应该把它提升一个层次,然后answer从 DOM 元素中设置我的 observable。

有没有人有任何想法/提示来实现这个工作?

更多信息

看来我之前解释的不够好,所以我会努力一点。

我的每个question对象都有一个名为controlType. 这表示应该在页面上绘制哪些 DOM 元素。因此,对于多个(例如)我应该有以下 DOM 元素:

<div class="question">
    <label class="question-label" data-bind="text: $data.text"></label>
    <select data-bind="value: $data.answer.month, options: [month names]"></select>
    <input type="text" data-bind="value: $data.answer.year" />
</div>

这将让用户回答一个问题 - 假设问题文本可能类似于您何时出生?然后上面的 DOM 结构允许他们提交月份和年份的答案,即Jan 1990。现在,在后台我需要从这两个 DOM 元素中获取值并将它们合并为一个单一的答案来设置question.answer属性。我尝试使用两个计算的可观察对象question.answer.monthquestion.answer.year但是随着我的控制类型变得更加复杂,我进入循环引用地狱,即我的答案取决于它的对应部分,而每一个对应部分都依赖于解析的答案。

简而言之 - 我试图根据未指定数量的 DOM 元素设置可观察的值,在这种(最简单的)情况下,它是一个SELECT和一个INPUT元素。

4

1 回答 1

1

这个答案提出了一个替代解决方案。

首先,使用模板绑定替换自定义绑定处理程序的使用。您的模板将如下所示:

<script type="text/html" id="Label">
    <h4 data-bind="value: answer"></h4>
</script>

<script type="text/html" id="TextBox">
    <input type="text" data-bind="value: answer" />
</script>

<script type="text/html" id="CheckBox">
    <input type="checkbox" data-bind="checked: answer, processControl: $data" />
</script>

<script type="text/html" id="Multiple">
    <select data-bind="value: answer, options: opts, optionsCaption: '-'"></select>
    <input type="text" data-bind="value: answerAddition" />
</script>

这可能是这里的主要问题和主要问题。以下是对您拥有的“多个”问题类型的一些想法,但我强烈建议您在这方面做更多工作,如果您遇到问题,请提出一个孤立的问题,因为如果您有一个问题,SO 往往效果最好时间。

PS。在这个小提琴中看到所有这些。请注意,几乎不再使用 jQuery,这通常是一个好兆头(至少是您使用 KO 的标志,因为它本来应该被使用)。

我认为您可能需要对那里的“复杂”/多个问题类型进行更多工作。以上是 IMO 朝着正确方向迈出的一步,还需要对数据和视图模型进行一些更改:

  • 数据将包含选项,例如
    opts: ['Jan', 'Feb', 'Mar' /*etc*/]

  • 视图模型将包含类似
    self.opts = ko.observableArray(data.opts || []);

  • 视图模型还将包含额外的 observable:
    self.answerAddition = ko.observable('');

  • 以及可能返回的只读计算:
    self.answer() + ' ' + self.answerAddition()

但是,我认为您会从进一步的几个步骤中受益,也许创建一些基于原型的继承并创建一个专门的 Question 构造函数来表示“月+年”。

于 2013-08-30T21:25:11.937 回答