8

これは、入力フィールドにバインドするときにノックアウトを使用してデータをサニタイズ/検証/フォーマットするための一般的なアプローチのようです。計算されたオブザーバブルを使用する再利用可能なカスタム バインディングを作成します。基本的に、デフォルト値バインディングを拡張して、書き込み/読み取りの前に入力をフォーマット/サニタイズ/検証するインターセプターを含めます。

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/

何か不足していますか?この方法がどこでも使用されているのを見てきましたが、完全には機能していないようです。read関数は全く慣れないので全く役に立たないようです..そしてwrite関数では「23.0000」と入力すると書き込み値が23に変わりますが、テキストボックスの値は更新されません。

4

1 に答える 1

13

この問題はupdate、カスタムバインディングの一部に起因します。この部分は、元のモデル値に基づいてフィールドを更新します。したがって、にアタッチされたイベントハンドラーはinit、書き込み可能な計算を介して新しい値を送信しますが、フィールドの更新は実際にはで行われupdateます。

1つのオプションは、関数から値バインディングを適用し、次のようなinit関数をスキップすることです。update

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/

于 2012-09-28T20:55:06.167 に答える