Knockout.js 使用拦截器扩展值绑定 [英] Knockout.js Extending value binding with interceptor

查看:19
本文介绍了Knockout.js 使用拦截器扩展值绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是在绑定到输入字段时使用敲除来清理/验证/格式化数据的常用方法,它创建了一个可重用的自定义绑定,该绑定使用计算的 observable.它基本上扩展了默认值绑定以包含一个拦截器,该拦截器将在写入/读取之前格式化/清理/验证输入.

This seems to be a common approach to sanitizing/validating/formatting data with knockout when binding to an input field, it creates a reusable custom binding that uses a computed observable. It basically extends the default value binding to include an interceptor that will format/sanitize/validate input before written/read.

ko.bindingHandlers.amountValue = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var underlyingObservable = valueAccessor();

    var interceptor = ko.computed({
      read: function () {
        // this function does get called, but it's return value is not used as the value of the textbox.
        // the raw value from the underlyingObservable is still used, no dollar sign added. It seems like 
        // this read function is completely useless, and isn't used at all
        return "$" + underlyingObservable();
      },

      write: function (newValue) {
        var current = underlyingObservable(),
            valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100) / 100;

        if (valueToWrite !== current) {
          // for some reason, if a user enters 20.00000 for example, the value written to the observable
          // is 20, but the original value they entered (20.00000) is still shown in the text box.
          underlyingObservable(valueToWrite);
        } else {
          if (newValue !== current.toString())
            underlyingObservable.valueHasMutated();
        }
      }
    });

    ko.bindingHandlers.value.init(element, function () { return interceptor }, allBindingsAccessor);
  },

  update: ko.bindingHandlers.value.update
};

jsFiddle 示例:http://jsfiddle.net/6wxb5/1/

jsFiddle example: http://jsfiddle.net/6wxb5/1/

我错过了什么吗?我已经看到这种方法到处都在使用,但似乎并没有完全奏效.read 函数似乎完全没用,因为它根本没有使用..,并且在 write 函数中,输入23.0000"会将写入的值更改为 23,但文本框值不会更新.

Am i missing something? I've seen this method used everywhere, but it doesn't seem to fully work. The read function seems completely useless as it doesn't get used at all.., and in the write function, entering "23.0000" changes the written value to 23, but the textbox values do not update.

推荐答案

该问题来自自定义绑定的 update 部分.这部分将根据原始模型值更新字段.因此,附加在 init 中的事件处理程序将通过您的可写计算发送新值,但字段的更新实际上发生在 update 中.

The issue comes from the update portion of your custom binding. This part will update the field based on the original model value. So, the event handler attached in the init will send the new value through your writeable computed, but the updating of the field actually happens in the update.

一种选择是应用 init 函数中的值绑定并跳过 update 函数,例如:

One option is to apply the value binding from your init function and skip the update function like:

ko.bindingHandlers.amountValue = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var underlyingObservable = valueAccessor();

    var interceptor = ko.computed({
      read: function () {
        // this function does get called, but it's return value is not used as the value of the textbox.
        // the raw value from the underlyingObservable, or the actual value the user entered is used instead, no   
        // dollar sign added. It seems like this read function is completely useless, and isn't used at all
        return "$" + underlyingObservable();
      },

      write: function (newValue) {
        var current = underlyingObservable(),
            valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100) / 100;

        if (valueToWrite !== current) {
          // for some reason, if a user enters 20.00000 for example, the value written to the observable
          // is 20, but the original value they entered (20.00000) is still shown in the text box.
          underlyingObservable(valueToWrite);
        } else {
          if (newValue !== current.toString())
            underlyingObservable.valueHasMutated();
        }
      }
    });

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

更新小提琴:http://jsfiddle.net/rniemeyer/Sr8Ev/

这篇关于Knockout.js 使用拦截器扩展值绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆