【问题标题】:Knockout.js : radio button first click does not show in 3.0, shows in 2.1-2.3Knockout.js : 单选按钮第一次点击在 3.0 中不显示,在 2.1-2.3 中显示
【发布时间】:2014-05-18 21:02:51
【问题描述】:

小提琴:http://jsfiddle.net/pr5YQ/7/

我在使用 Knockout.js 时遇到了一个相对常见的问题 - 每当第一次选择单选按钮时,对象模型中的值都会更新,但单选按钮本身不会显示选择。在第二次选择时,该项目显示检查。

有趣的是,Knockout 版本 2 可以正常工作!只有 Knockout 版本 3 有问题。在小提琴中,切换到任何版本的 Knockout 2,表单将根据需要工作。

我检查了我设置为值的数据类型是否有任何问题(它们都是数字,应该没问题)并且名称/值设置似乎是正确的。我希望,如果我没有执行上述任何一项操作,那么第一次点击失败将显示在所有版本的 Knockout 中。

这是我拥有的数据模型的 sn-p:

        "Question_Ref": 1,
            "Question_Text": "Question 1",
            "Response_Ref": -1,
            "Response_Text": "",
            "Selected_Answer_Ref": -1,
            "Answers": [{
            "Answer_Ref": 1,
                "Answer_Text": "Yes",
                "Answer_Fails": false
        }, {
            "Answer_Ref": 2,
                "Answer_Text": "No",
                "Answer_Fails": false
        }]

以下是我获取数据对象本身并附加必要的 KO 绑定的方法:

function AttachKOObjectsOnQuestion(question) {
    question.Selected_Answer_Ref_KO = ko.observable(question.Selected_Answer_Ref);
    question.Show_Response_KO = ko.computed({
        read: function () {
            if (!question.Selected_Answer_Ref_KO()) return null;
            if (question.Selected_Answer_Ref_KO() < 0) return null;
            for (selAnswerCount = 0; selAnswerCount < this.Answers.length; selAnswerCount++) {
                var answer = this.Answers[selAnswerCount];
                if (answer.Answer_Ref === this.Selected_Answer_Ref_KO()) {
                    return answer.Answer_Fails;
                }
            }
            return null
        },
        write: function (value) {},
        owner: question
    });
    var answerCount;
    for (answerCount = 0; answerCount < question.Answers.length; answerCount++) {
        AttachKOObjectsOnQuestionAnswer(question, question.Answers[answerCount]);
    }
}

function AttachKOObjectsOnQuestionAnswer(question, answer) {
    answer.ParentQuestion = question;
    answer.Selected_Answer_Ref_KO = ko.computed({
        read: function () {
            return answer.ParentQuestion.Selected_Answer_Ref_KO();
        },
        write: function (value) {
            var selectedAnswer = parseInt(value, 10);
            answer.ParentQuestion.Selected_Answer_Ref_KO(selectedAnswer);
        },
        owner: answer
    });
}

这是单选按钮的相关设置:

<table cellpadding="0" cellspacing="0">
    <tbody data-bind="foreach: Answers">
        <tr>
            <td>
                <input type="radio" data-bind="attr: { value: Answer_Ref, name: ParentQuestion.Question_Ref }, checked: Selected_Answer_Ref_KO, click: hideValidators" />
            </td>
            <td>
                <span data-bind="text: Answer_Text"></span>
            </td>
        </tr>
    </tbody>
</table>

这是我第一次使用 Knockout 和 JSON,因此请随时提出批评。谢谢!

【问题讨论】:

  • 我已经回答了您的问题,但是请您下次提出问题时,尝试创建 minimal example 而不是提供此代码块(尽管如此,即使在jsfiddle 的最小示例案例有很大帮助)。您可能会在创建最小示例时自己发现问题,即使您没有发现,任何想要帮助您的人都需要阅读的代码要少得多。
  • 谢谢。我应该删除所有的废话(只是测试它是否导致问题)但我忘记了。你不是唯一一个指出这一点的人,我需要在未来提供可行的例子方面做得更好。
  • 这里的简化代码:http://jsfiddle.net/pr5YQ/7/

标签: javascript knockout.js


【解决方案1】:

您的问题是单选按钮上的checked 绑定不正确。您正在尝试将checked 绑定到您的答案中名为Selected_Answer_Ref_KO 的属性。但是,您已将该对象添加到问题中,而不是答案中。

要解决此问题,只需将您的 checked 绑定更改为 checked: $parent.Selected_Answer_Ref_KO。我已经用这个变化更新了你的小提琴,并且第一次点击时选择工作。您可以在 http://jsfiddle.net/pr5YQ/5/ 找到该更新。

【讨论】:

  • 答案上其实有一个同名的KO计算函数。如果您返回到初始版本,您会看到在某些情况下应该显示/隐藏响应,而这不起作用的事实可能表明该值没有被设置。也就是说,我应该开始使用 $parent,而不是自己显式添加父对象。似乎我设置的每个属性都会减慢页面渲染速度,所以我应该删除任何可以删除的内容。
  • http://jsfiddle.net/pr5YQ/9/ 添加了 $parent 并进一步简化了。警报显示数据模型正在像以前一样更新。
【解决方案2】:

这是在 Facebook 上的 by Adam Rackis 回答的。

Knockout 3 使用严格比较,我没有意识到输入值中的任何内容都是字符串。因此,单选按钮的值(字符串)永远不会与我的数据模型的值(数字)匹配。

更糟糕的是,我错过了文档中提到您可以使用 checkedValue 绑定来设置非字符串的值。这是解决我的问题的正确方法,因为我希望我的数据模型的当前类型保持为数字。

<input type="radio" data-bind="attr: { name: ParentQuestion.Question_Ref }, checkedValue : Answer_Ref, checked: Selected_Answer_Ref_KO, click: hideValidators" />

【讨论】:

    猜你喜欢
    • 2014-06-04
    • 2013-02-27
    • 2021-05-22
    • 2020-06-12
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    相关资源
    最近更新 更多