2012-01-17 4 views
3

私は私のViewModelのboolean型プロパティの逆数にチェックボックスと別のDOM要素の可視性をバインドする必要があるとき、私はケースを持っている:チェックボックスを値の逆にバインドする方法はありますか?

<input type="checkbox" data-bind="checked: needsReview"> Not Required 
<br> 
<div id="Some related text" data-bind="visible: needsReview"> other stuff here </div> 
var dataFromSever = { needsReview: true }; 

var theModel = function (jsonData) { 
    var self = this; 
    ko.mapping.fromJS(jsonData, {}, self); 
} 

ko.applyBindings(new theModel(dataFromSever)); 

私はこののように複数のプロパティを持っています私の実際のデータモデルなので、複数のフィールドを作成する必要はありませんko.computed()フィールド。私はちょうど"checked: !needsReview()"にバインドしたいと思っています。

答えて

11

これを処理するのに似たような方法がいくつかあります。基本的な考え方は、チェックボックスをバインドするための書き込み可能な計算オブザーバブルを作成する必要があるということです。

これは、モデルで直接、エクステンダを使用して、または観察可能なベース(ko.observable.fn)に関数を追加することで行うことができます。

しかし、マッピングプラグインを使用しているため、オブジェクトの作成方法をカスタマイズしたりプロパティを追加したりしたくないので、カスタムバインディングを使用するのが最適な方法だと思います。あなたのモデルは本当にあなたのプロパティの逆を維持することに関心を持つ必要はないので、バインディング中にこの部分を実際に行うことができます。

実際の観測値とバインディングの間に書き込み可能な計算可能なオブザーバブルを挿入するinverseCheckedバインディングがあります。次に、実際にチェックされたバインディングを使用して作業を行います。ここで

ko.bindingHandlers.inverseChecked = { 
    init: function(element, valueAccessor, allBindingsAccessor) { 
     var value = valueAccessor(); 
     var interceptor = ko.computed({ 
          read: function() { 
           return !value(); 
          }, 
          write: function(newValue) { 
           value(!newValue); 
          }, 
          disposeWhenNodeIsRemoved: element 
         }); 

     var newValueAccessor = function() { return interceptor; }; 


     //keep a reference, so we can use in update function 
     ko.utils.domData.set(element, "newValueAccessor", newValueAccessor); 
     //call the real checked binding's init with the interceptor instead of our real observable 
     ko.bindingHandlers.checked.init(element, newValueAccessor, allBindingsAccessor); 
    }, 
    update: function(element, valueAccessor) { 
     //call the real checked binding's update with our interceptor instead of our real observable 
     ko.bindingHandlers.checked.update(element, ko.utils.domData.get(element, "newValueAccessor")); 
    } 
}; 

はサンプルです:あなたはvisible: !needsReview()

+3

ありがとうございます。これはまさに私が必要とするもののように見えます。それは本当にそれがこれより簡単であるように思えるでしょうか?私は今朝それを繋ぐことができないかどうか見てみましょう... – ShaneBlake

+0

正確に私が必要としたもの。ありがとうございました... – ShaneBlake

+0

クールな回答、右。でも、ラジオボタンだけではないのはなぜですか? –

2

私は一般的にvisibleの逆数であるKOでカスタムbindingHandlerます

ko.bindingHandlers['invisible'] = { 

    update: function(element, valueAccessor){ 
     var val = ko.utils.unwrapObservable(valueAccessor()); 

     ko.bindingHandlers['visible'].update(element, function() { return !val; });    
    } 
} 

あなたは醜い!val()

であなたの data-bind文を乱雑にすることなく、説明してきたように、あなたがきれいなニーズの世話をすることができます
+0

ありがとうございますが、これは 'visible'バインディングのみを処理します。 'checkbox'バインディングの問題は修正されません。 – ShaneBlake

+0

ええ - ライアンは質問の残りの半分でパンチに私を倒した。これらのバインディングハンドラを両方ともプロジェクトに追加すると、バインディングステートメントをきれいにすることができます。 – ericb

0

Iが観測値/演算値を反転させる、より汎用的かつ普遍的な方法を好むを行うことができますバインディングごvisibleについてはhttp://jsfiddle.net/rniemeyer/Kz4Tf/

(つまりに依存しません任意の特異的結合):

/** 
* A small handy observable/computed function that wraps around the inverse of it's boolean value. 
* @author Nir Azuelos 
* @returns {Function} 
*/ 
ko.observable.fn.inverse = ko.computed.fn.inverse = function() { 
    return ko.pureComputed(function() { return !this(); }, this); 
}; 

用途:

<div data-bind="visible: myObservable.inverse()"> 
関連する問題