テーブルをノックアウトでバインドする必要があり、新しい値が以前の値よりも高いまたは低い場合、テーブル セルに別の css クラスを取得させたいと考えています。
以前の値を bindingContext に格納し、適切なクラスを返す関数を使用するなど、さまざまな可能性を念頭に置いていますが、以前の値と新しい値を受け取るカスタム バインディング ハンドラーを追加することは可能ですか?
テーブルをノックアウトでバインドする必要があり、新しい値が以前の値よりも高いまたは低い場合、テーブル セルに別の css クラスを取得させたいと考えています。
以前の値を bindingContext に格納し、適切なクラスを返す関数を使用するなど、さまざまな可能性を念頭に置いていますが、以前の値と新しい値を受け取るカスタム バインディング ハンドラーを追加することは可能ですか?
JeffとSławomirの回答は機能しますが、ビュー モデルを変更する必要がなく、DOM 要素オブジェクトの変更に依存しない代替案を見つけました。
function subscribeToPreviousValue(observable, fn) {
observable.subscribe(fn, this, 'beforeChange');
}
ko.bindingHandlers['bindingWithPrevValue'] = {
init: function (element, valueAccessor) {
var observable = valueAccessor();
var current = observable();
console.log('initial value is', current);
subscribeToPreviousValue(observable, function (previous) {
console.log('value changed from', previous, 'to', current);
});
}
};
当然、バインドされたプロパティが監視可能である場合にのみ機能します。
できることは、以前の値を追跡したいオブザーバブルを拡張するエクステンダーを作成することです。次に、前の値を調べて、必要に応じて実行できます。
前の値を保持するプロパティの名前を渡すだけです。
ko.extenders.previousValue = function (target, propertyName) {
var previousValue = ko.observable(null);
target[propertyName] = ko.computed(previousValue);
target.subscribe(function (oldValue) {
previousValue(oldValue);
}, target, 'beforeChange');
return target;
};
次にそれを使用するには:
function ViewModel() {
this.value = ko.observable('foo').extend({ previousValue: 'previousValue' });
}
var vm = new ViewModel();
console.log(vm.value()); // 'foo'
console.log(vm.value.previousValue()); // null
vm.value('bar');
console.log(vm.value()); // 'bar'
console.log(vm.value.previousValue()); // 'foo'
あなたの場合、おそらく次のようなものを使用できます。
function TableCell(value) {
this.value = ko.observable(value).extend({ previousValue: 'previousValue' });
this.cssClass = ko.computed(function () {
// I'm assuming numbers
var current = Number(this.value()),
previous = Number(this.value.previousValue());
if (current < previous)
return 'lower';
else if (current > previous)
return 'higher';
}, this);
}
ノックアウトソースを調べたところ、bindingHandler の update メソッド内で以前の値にアクセスすることはできませんが、要素内に格納することはできると思います。
ko.bindingHandlers['bindingWithPrevValue'] = {
update: function (element, valueAccessor) {
var prevValue = $(element).data('prevValue');
var currentValue = valueAccessor();
$(element).data('prevValue', currentValue());
// compare prevValue with currentValue and do what you want
}
};