46

ノックアウトjsでバインド時に引数を渡すことができるかどうか疑問に思っています。

チェックボックスのリストをバインドしていますが、ビューモデルで計算された単一のオブザーバブルにバインドしたいと考えています。ビューモデル (読み取り関数に渡されるパラメーターに基づく) では、特定の条件に基づいて true/false を返したいと考えています。

var myViewModel=function(){
    this.myprop=ko.computed({read: function(){
    //would like to receive an argument here to do my logic and return based on argument.
}
});
};

<input type="checkbox" data-bind="checked: myprop(someval1)" />
<input type="checkbox" data-bind="checked: myprop(someval2)" />
<input type="checkbox" data-bind="checked: myprop(someval3)" />

助言がありますか?

4

4 に答える 4

89

計算されたオブザーバブルを返すことを唯一の目的とする関数を作成します。必要に応じてパラメーターを受け取ることができます。双方向バインディングにしたい場合は、別の計算されたオブザーバブルである必要があります。

次に、バインディングで、適切な引数を使用してその関数を呼び出します。返される計算されたオブザーバブルはビューにバインドされ、通常どおり更新されます。

これは、イベント ハンドラーを作成するためにこの手法を使用したフィドルです。ここで同様のことができます。

関数をオブザーバブルのメソッドにすることで、きれいに保つことができます。プロトタイプに追加するかko.observable.fn、監視可能なインスタンスに直接追加します。

ko.observable.fn.bit = function (bit) {
    return ko.computed({
        read: function () {
            return !!(this() & bit);
        },
        write: function (checked) {
            if (checked)
                this(this() | bit);
            else
                this(this() & ~bit);
        }
    }, this);
};
// or
function ViewModel() {
    this.flags = ko.observable(0);

    this.flags.bit = function (bit) {
        return ko.computed({
            read: function () {
                return !!(this() & bit);
            },
            write: function (checked) {
                if (checked)
                    this(this() | bit);
                else
                    this(this() & ~bit);
            }
        }, this);
    }.bind(this.flags);
}    

次に、ビューに適用します

<input type="checkbox" data-bind="checked: flags.bit(0x1)"/>
<input type="checkbox" data-bind="checked: flags.bit(0x2)"/>
<input type="checkbox" data-bind="checked: flags.bit(0x4)"/>
<input type="checkbox" data-bind="checked: flags.bit(0x8)"/>

デモ


ただし、これらすべてのチェックボックスをビュー モデル内の単一の値にバインドしようとしているだけの場合は、その必要はありません。checkedビュー モデルの配列でバインディングを使用し、チェックボックスに値を指定します。チェックされたすべての値が配列に追加されます。そして、それは双方向バインディングになります。

<input type="checkbox" data-bind="checked: checkedValues, value: 1"/>
<input type="checkbox" data-bind="checked: checkedValues, value: 2"/>
<input type="checkbox" data-bind="checked: checkedValues, value: 3"/>
<input type="checkbox" data-bind="checked: checkedValues, value: 4"/>
var viewModel = {
    checkedValues: ko.observableArray([])
};

デモ

于 2012-11-04T06:29:22.150 に答える
3

computed値を使用する理由はありません。ビュー モデルで関数を定義し、それにバインドするcheckedだけです。

以下は非常に単純な例です。

--

HTML

<input type="checkbox" data-bind="checked: isEven(1)" />
<input type="checkbox" data-bind="checked: isEven(2)" />
<input type="checkbox" data-bind="checked: isEven(3)" />​

JS

var MyViewModel=function(){
    this.isEven = function(num) {
        return (num % 2) == 0;
    };
};
ko.applyBindings(new MyViewModel());

--

そうは言っても、できるだけ多くのロジックをビュー モデルにプッシュすることをお勧めします。チェックボックスをオブジェクトとしてモデル化するビューモデルを作成し、チェックボックスをオンにする必要があるかどうかのロジックを内部にカプセル化することをお勧めします。

--

編集:双方向バインディングを行うという要件に基づいて、オブザーバブルを管理するためのエクステンダーを作成しました。

http://jsfiddle.net/jearles/j6zLW/5/

ko.extenders.bitwise = function(target, bitCount) { 
    target.bits = [];    
    target.checked = ko.observableArray();

    // Create bit array based on requested number of bits
    for (i=bitCount-1; i>=0; i--) {
        target.bits.push(''+Math.pow(2, i));
    }        

    // Define a function to create bits
    function makeBits(newValue) {
       var num = !isNaN(newValue) ? parseInt(newValue) : 0;
       var arr = [];
       for (i=0; i<target.bits.length; i++) {
          var bitValue = parseInt(target.bits[i]);
          if ((num & bitValue) == bitValue) arr.push(target.bits[i]);
       }
       target.checked(arr);
    }

    // Define a function to combine bits
    function makeBitwise(newBits) {
       var num = 0;
       for (i=0; i<target.bits.length; i++) {
         if (newBits.indexOf(target.bits[i]) > -1) num += parseInt(target.bits[i]);
       }
       target(num);
    }

    // Create initial bits
    makeBits(target());

    // Make bits whenever the value changes
    target.subscribe(makeBits);

    // Make number whenever the bits change
    target.checked.subscribe(makeBitwise);

    // Return the original observable
    return target;
};

var MyViewModel=function(){
    var self = this;
    this.number = ko.observable(2).extend({ bitwise: 8});

};
ko.applyBindings(new MyViewModel());​
于 2012-11-03T16:44:35.473 に答える
0

詳細を知らなくても、ko.observableArray または計算された配列値を定義する必要があるようです。

HTML:

myprop: <input data-bind="value: myprop">
<div data-bind="foreach: selections">
  <label>
    <span data-bind="text: value"></span>
    <input type="checkbox" data-bind="checked: selected"/>
  </label>
</div>

JS:

  $(function() {
    function Model() {
        this.self = this
        self.myprop = ko.observable(14)
        self.bits = [1, 2, 4, 8, 16, 32, 64, 128]
        self.selections = ko.computed(function() {
            return self.bits.map(function(bit) {
                console.log(myprop() & bit)
                return {
                    value: bit,
                    selected: (myprop() & bit) == bit
                }
            })
        })
    }

    ko.applyBindings(new Model())
})

モデルの状態を定義するためにマークアップから値を渡さない

于 2012-11-03T16:32:11.553 に答える