Javascript 剔除自定义处理程序以隐藏禁用的文本框值

Javascript 剔除自定义处理程序以隐藏禁用的文本框值,javascript,knockout.js,Javascript,Knockout.js,我有一个表单,它基本上有一些属性,这些属性在几个项目之间共享。当您为文本框启用数据输入的项目选择单选按钮时,一次只能选择一个项目 我已经完成了所有设置和工作,但如果控件被禁用,我不希望绑定值显示在文本框中。我一直在尝试与管理人员合作,但我正在经历一段痛苦的时光,试图了解如何让事情按照我需要的方式进行。我看过Ryan和他提供的定制处理程序的许多文章,但我需要顿悟,但在此之前,我正在寻求您的帮助。还有,有没有更合适的方法来处理我创建的IsEnabled函数,或者这是最好的方法 这是你的电话号码 更新

我有一个表单,它基本上有一些属性,这些属性在几个项目之间共享。当您为文本框启用数据输入的项目选择单选按钮时,一次只能选择一个项目

我已经完成了所有设置和工作,但如果控件被禁用,我不希望绑定值显示在文本框中。我一直在尝试与管理人员合作,但我正在经历一段痛苦的时光,试图了解如何让事情按照我需要的方式进行。我看过Ryan和他提供的定制处理程序的许多文章,但我需要顿悟,但在此之前,我正在寻求您的帮助。还有,有没有更合适的方法来处理我创建的IsEnabled函数,或者这是最好的方法

这是你的电话号码

更新了,我尝试创建一个自定义处理程序来禁用并删除该值,而不是执行该值。它可以正常工作,但在几次更新后就会停止,并且值不会得到更新

以下是一些示例HTML:

<ul>
    <li>
        <input type="radio" name="item" value="1" data-bind="checked:Selected" /> Item 1 <input type="text" data-bind="value:Price, enable:IsEnabled('1')" />
        </li>
    <li>
        <input type="radio" name="item" value="2" data-bind="checked:Selected" /> Item 2 <input type="text" data-bind="value:Price, enable:IsEnabled('2')" />
        </li>
    <li>
        <input type="radio" name="item" value="3" data-bind="checked:Selected" /> Item 3 <input type="text" data-bind="enabledValue:Price, enable:IsEnabled('3')" />
        </li>
    <li>
        <input type="radio" name="item" value="4" data-bind="checked:Selected" /> Item 4 <input type="text" data-bind="enabledValue:Price, enable:IsEnabled('4')" />
        </li>
</ul>

托尼。我刚刚简化了您的示例,让它在不同项目之间共享相同的值属性。绑定将存储内部计算数据并将元素绑定到其上的主要思想

extend(handlers, {
    enableValue: {
        init: function (element, valueAccessor, allBindings) {

            var showValue = ko.computed({
                read: function(){
                    if (unwrap(allBindings().enable)) {
                        return unwrap(valueAccessor());
                    } else {
                        return '';
                    }
                },
                write: valueAccessor()
            });

            ko.applyBindingsToNode(element, { value: showValue });

        }
    }
});

请注意,在KO 3.0中,
KO.applybindingstoode
被重命名为
KO.applybindingaccessorstoode

但是让绑定记住每个项最后输入的值不是更有意义吗?实现起来非常简单

更新

记住特定项的上一次编辑值的方式类似于在内部保留该值,如
showValue
。让我们把它命名为
lastValue

extend(handlers, {
    enableValue: {
        init: function (element, valueAccessor, allBindings) {

            // Create observable `lastValue` with some default content.
            // It will be created for EVERY binding separately.
            var lastValue = ko.observable(0);

            // If an item is currently enabled then set `lastValue` to the actual value.
            if (unwrap(allBindings().enable)) lastValue(unwrap(valueAccessor()));
            // This piece will be executed only once (for the selected item) and other
            // items will store default value in `lastValue`!

            // It's the internal anonymous computed intended to update bound
            // price to reflect currently edited value.
            ko.computed(function(){
                if (unwrap(allBindings().enable)) valueAccessor()(lastValue());
            });
            // Note that passed function will be triggered whenever item is enabled
            // and/or `lastValue` changes.

            // Here we just change valueAccessor() to `lastValue`.
            var showValue = ko.computed({
                read: function(){
                    if (unwrap(allBindings().enable)) {
                        return lastValue();
                    } else {
                        return '';
                    }
                },
                write: lastValue
            });

            ko.applyBindingsToNode(element, { value: showValue });

        }
    }
});


我希望这几乎是你所期望的。通常在这种情况下,真正的问题不是实现某个功能,而是描述该功能应该如何工作。

由于我对答案的补充内容已被编辑掉,因此我添加此答案是为了帮助那些新加入KO的人

下面是一个使用KO.applybindingAccessorNode的KO 3.0实现

extend(handlers, {
    enableValue: {
        init: function (element, valueAccessor, allBindings) {

            var showValue = ko.computed({
                read: function () {
                    if (unwrap(allBindings().enable)) {
                        return valueAccessor(); // CHANGED
                    } else {
                        return '';
                    }
                },
                write: valueAccessor //CHANGED
            });

            ko.applyBindingAccessorsToNode(element, { value: showValue }); //CHANGED

        }
    }
});
正如发行说明中所述,目前还没有正式的文档,但这是我能够整理的。我使用组消息来确定差异。希望这将节省一些时间,直到它有更多的文档

ko.applybindingstoode被替换为 ko.applyBindingAccessorNode。第二个参数接受一个对象 具有成对的绑定和值访问器(返回 绑定值)。它还可以接受一个函数,该函数返回这样一个 对象(此界面目前未在网站上记录。)

迈克尔·贝斯特说这更好


像这样的。如果您愿意,可以以更好的方式对其进行规范化。cheers@supercool我正在考虑做类似的事情,但我有15个字段必须这样做,我试图避免创建额外的元素。不过谢谢你,因为这确实有效。只是替代方案从来都不是一个合适的方法。很高兴下面有更好的解决方案。干杯简化是对的,这太棒了。我昨天花了很多时间想把这件事弄清楚。我仍然抱着ko,我看到并理解你现在在做什么,但即使从那里我也不知道如何记住你提到的最后一个价值观,思想共享?我将把这个标记为答案,因为这是工作现场,但后续也将感谢,再次感谢!!!我提交了一个添加3.0版本的编辑,我花了一点时间找到了一个很好的参考来转换它,我只是在研究applyBindingToNode函数时偶然发现了你的一个问题。谢谢你,添加了额外的代码,这真的很有帮助!你能给我一个关于
ko.applybindingstoode
弃用的链接吗?这非常令人困惑,因为
ko.applybindingstoode
ko.applybindingaccessorstoode
用于不同的用途。您可以检查我的答案中的更改函数是否会使示例停止工作(可编辑值将变为只读)。@f_martinez,现在还没有太多内容,但我添加了一些有用的内容。
extend(handlers, {
    enableValue: {
        init: function (element, valueAccessor, allBindings) {

            var showValue = ko.computed({
                read: function () {
                    if (unwrap(allBindings().enable)) {
                        return valueAccessor(); // CHANGED
                    } else {
                        return '';
                    }
                },
                write: valueAccessor //CHANGED
            });

            ko.applyBindingAccessorsToNode(element, { value: showValue }); //CHANGED

        }
    }
});