9

ビューモデルに3つの観測可能な変数があり、フォーマットされた値に出力したいと思います。ただし、それらは同一であるため、それぞれの計算メソッドを記述したくありません。コードを再利用するための最良の方法は何ですか?ありがとう。

私が達成しようとしているコードは次のとおりです。

   this.formattedPrice = ko.computed({
        read: function () {
            return '$' + this.price().toFixed(2);
        },
        write: function (value) {
            // Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            this.price(isNaN(value) ? 0 : value); // Write to underlying storage
        },
        owner: this
    });

そして失敗した例は次のとおりです:Jsfiddle

ありがとう、

4

1 に答える 1

17

これを再利用可能にする方法はいくつかあります。

ビューモデルでこれを処理する場合は、フォーマットされた計算されたオブザーバブルを元の「サブオブザーバブル」として格納する拡張機能を作成することをお勧めします。エクステンダーを使用するか、ここで説明するように共有fnオブジェクトに追加することで、オブザーバブルを拡張できます。私は後者が好きです。

したがって、と呼ばれるオブザーバブルに関数を追加できますwithCurrencyFormat。次のようになります。

ko.observable.fn.withCurrencyFormat = function(precision) {
    var observable = this;
    observable.formatted = ko.computed({
        read: function (key) {
            return '$' + (+observable()).toFixed(precision);
        },
        write: function (value) {
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            observable(isNaN(value) ? null : value); // Write to underlying storage 
        }        
    }); 

    return observable;
};

今、あなたは言うことができます:

 self.week1Amount = ko.observable(w1).withCurrencyFormat(2);
 self.week2Amount = ko.observable(w2).withCurrencyFormat(2);
 self.week3Amount = ko.observable(w3).withCurrencyFormat(2);

次のようにUIでバインドします。

    <td><input data-bind="value: week1Amount.formatted" /></td>
    <td><input data-bind="value: week2Amount.formatted" /></td>
    <td><input data-bind="value: week3Amount.formatted" /></td>

こちらのサンプル:http://jsfiddle.net/rniemeyer/xskJN/

もう1つの選択肢は、これをバインディングに移動して、ビューモデルをそのままにしておくことです。これは同様のコードを使用しますが、次のようなカスタムバインディングハンドラーで使用されます。

ko.bindingHandlers.valueAsCurrency = {
    init: function(element, valueAccessor) {
        var observable = valueAccessor(),
            formatted = ko.computed({
                read: function (key) {
                    return '$' + (+observable()).toFixed(2);
                },
                write: function (value) {
                    value = parseFloat(value.replace(/[^\.\d]/g, ""));
                    observable(isNaN(value) ? null : value); // Write to underlying storage 
                },
                disposeWhenNodeIsRemoved: element                
            });

        //apply the actual value binding with our new computed
        ko.applyBindingsToNode(element, { value: formatted });
    }        
};

したがって、バインディングハンドラーでは、計算を作成し、それvalueに対してバインディングを使用します。

これで、ビューモデルを変更する必要がなくなり、次のようにUIにバインドします。

    <td><input data-bind="valueAsCurrency: week1Amount" /></td>
    <td><input data-bind="valueAsCurrency: week2Amount" /></td>
    <td><input data-bind="valueAsCurrency: week3Amount" /></td>

こちらのサンプル:http://jsfiddle.net/rniemeyer/sD6y4/

于 2012-12-21T21:20:08.060 に答える