【问题标题】:input type=reset and knockout输入类型=重置和淘汰赛
【发布时间】:2013-03-31 03:33:32
【问题描述】:

当点击表单重置按钮时,Knockout 不会更新 observables。

http://jsfiddle.net/nQXeM/

HTML:

<form>
    <input type="text" data-bind="value: test" />
    <input type="reset" value="reset" />
</form>
<p data-bind="text: test"></p>

JS:

function ViewModel() {
    this.test = ko.observable("");
}

ko.applyBindings(new ViewModel());

显然输入框的更改事件没有被触发,如以下 jQuery 测试所示: http://jsfiddle.net/LK8sM/4/

如果重置按钮未触发更改事件,我们将如何强制所有绑定到表单输入的可观察对象进行更新,而无需手动指定它们?

使用 jQuery 来查找表单内的所有输入并触发更改事件很容易,但假设我们有一个仅淘汰赛控制的表单。

【问题讨论】:

  • 您反对将重置实现为视图模型方法吗?正如您所指出的,这似乎是与resets 不触发更改相关的更大问题,这可能是一个重大问题。
  • 如果视图模型中的方法可以重置所有可观察对象,而无需手动列出它们,那么它将起作用。但我真的只想重置绑定到输入的可观察对象。

标签: forms knockout.js


【解决方案1】:

正如您所提到的,重置表单时不会触发 change 事件。如果您只使用 KnockOut,我认为您真的没有可能的选择,除非您创建可以注册 reset 事件并检测更改的自定义绑定 - 这仍然涉及手动 JS,但至少它将是集中式的.

虽然确实需要 jQuery,但更通用的方法是创建一个函数来处理表单的 reset 事件,并检测当时表单输入的变化。

这是一个可能有效的事件处理程序示例。请注意,这不是生产就绪代码。在使用之前,我会用 jQuery 的眼光来看待它:)

$('form').on('reset', function (evt) {
    evt.preventDefault();
    $(this).find('input, select, textarea').each(function () {
        if ($(this).is('input[type="radio"], input[type="checkbox"]')) {
            if ($(this).is(':checked') !== $(this)[0].defaultChecked) {
                $(this).val($(this)[0].defaultChecked);
                $(this).trigger('click');
                $(this).trigger('change');
            }
        } else {
            if ($(this).val() !== $(this)[0].defaultValue) {
                $(this).val($(this)[0].defaultValue);
                $(this).change();
            }
        }
    });
});

这是一个演示这个想法的小提琴:http://jsfiddle.net/Fm8rM/2/

【讨论】:

    【解决方案2】:

    我复制并修改了default Knockout submit binding,以便为表单重置事件创建类似的绑定:

    ko.bindingHandlers['reset'] = {
        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            if (typeof valueAccessor() !== 'function')
                throw new Error('The value for a reset binding must be a function');
    
            ko.utils.registerEventHandler(element, 'reset', function (event) {
                var handlerReturnValue;
                var value = valueAccessor();
    
                try {
                    handlerReturnValue = value.call(bindingContext['$data'], element);
                } finally {
                    if (handlerReturnValue !== true) {
                        if (event.preventDefault)
                            event.preventDefault();
                        else
                            event.returnValue = false;
                    }
                }
            });
        }
    };
    

    你可以这样绑定:

    <form data-bind="reset: onFormReset">
    

    onFormReset 将出现在您的视图模型上:

    function ViewModel() {
        this.onFormReset = function () {
            //Your custom logic to notify or reset your specific fields.
    
            return true;
        }
    }
    

    在您的重置处理程序中,如果您返回 true,那么 JavaScript 将继续在表单上调用其重置函数。但是,如果您正在设置绑定到 value 的 observable,则实际上不需要让 JavaScript 继续重置表单。因此,从技术上讲,您可以不返回任何内容,或者在这种情况下返回 false。

    其他人可以进一步扩展它以自动通知表单中所有绑定的 observables,但这对我的目的有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 2013-04-10
      • 1970-01-01
      • 2014-01-17
      • 2012-06-06
      • 2015-06-02
      相关资源
      最近更新 更多