【问题标题】:Updating an observable from a dynamically created input element从动态创建的输入元素更新 observable
【发布时间】:2013-09-02 16:09:18
【问题描述】:

Example 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 属性。我创建了一个自定义绑定处理程序来在表单上绘制输入,并创建另一个处理程序来处理基于所创建控件的 DOM 结构的answer

例如,对于一个特定的控件类型,我将 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 元素观察到。

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

更多信息

好像我之前解释的不够清楚,所以我再努力一点。

我的每个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 结构允许他们提交月份和年份的答案,即1990 年 1 月。现在,在后台我需要从这两个 DOM 元素中获取值并将它们合并为一个单一的答案来设置 question.answer 属性。我尝试使用两个计算的 observables question.answer.monthquestion.answer.year,但是随着我的控制类型变得更加复杂,我进入了循环引用地狱,即我的答案取决于它的对应部分,而每一个对应部分都依赖于解析的答案。

简而言之 - 我试图根据未指定数量的 DOM 元素设置 observable 的值,在这种(最简单的)情况下,它是 SELECTINPUT 元素。

【问题讨论】:

  • 抱歉,我不明白什么是不正确的。你能描述一下你的小提琴有什么问题吗?现在发生的事情应该发生的事情。
  • @nemesv 抱歉回复晚了,我有两个 3 个月大的孩子需要持续关注!我添加了更多信息,希望对您有所帮助?

标签: knockout.js


【解决方案1】:

这个答案提出了另一种解决方案。

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

<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。在this fiddle 中查看所有这些工作。请注意,jQuery 几乎不再使用了,这通常是一个好兆头(至少是您使用 KO 的标志,因为它本来应该被使用)。

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

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

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

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

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

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

【讨论】:

  • 谢谢你,我的问题是我有很多控制类型和很多不同的对应部件,所以我试图避免每种控制类型都有一个特定的模型。我试图将 DOM 访问排除在我的模型之外(因此使用自定义绑定),但我认为如果我可以从给定组中的特定 DOM 元素设置我的答案,它将更具可扩展性。模板的想法很好,我可以很高兴地摆脱 renderControl 绑定以支持模板。
猜你喜欢
  • 1970-01-01
  • 2020-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 2019-01-02
  • 1970-01-01
相关资源
最近更新 更多