最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to define a custom binding who use previous value to determine class in Knockout? - Stack Overflow

programmeradmin0浏览0评论

I need to bind a table with knockout, and I would like the table cell to get a different css class if the new value is higher or lower of the previous.

I have in mind different possibilities, such as storing the previous value in the bindingContext and have a function which returns the right class, but is it possible to add a custom binding handler which receives the previous value and the new value?

I need to bind a table with knockout, and I would like the table cell to get a different css class if the new value is higher or lower of the previous.

I have in mind different possibilities, such as storing the previous value in the bindingContext and have a function which returns the right class, but is it possible to add a custom binding handler which receives the previous value and the new value?

Share Improve this question asked Feb 24, 2013 at 19:34 EdmondoEdmondo 20.1k14 gold badges66 silver badges124 bronze badges 1
  • Can you describe a bit more the scenario? What does previous mean, on the same row or column? A sample data structure would help too. – Vlad Stirbu Commented Feb 24, 2013 at 20:23
Add a ment  | 

3 Answers 3

Reset to default 4

Although Jeff's and Sławomir's answers would work, I found an alternative that doesn't need any change to the view model nor relies on altering the DOM element object.

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);
    });
  }
};

Naturally, that will only work if the bound property is an observable.

I looked into knockout source and I suppose that you can't access previous value inside update method of bindingHandler but you can store it inside element

ko.bindingHandlers['bindingWithPrevValue'] = {
    update: function (element, valueAccessor) {
        var prevValue = $(element).data('prevValue');
        var currentValue = valueAccessor();
        $(element).data('prevValue', currentValue());

        // pare prevValue with currentValue and do what you want
    }
};

What you could do is create an extender to extend the observables that you wish to track the previous values of. You could then inspect the previous value to do as you wish.

Just pass in the name of the property that will hold the previous value.

ko.extenders.previousValue = function (target, propertyName) {
    var previousValue = ko.observable(null);

    target[propertyName] = ko.puted(previousValue);

    target.subscribe(function (oldValue) {
        previousValue(oldValue);
    }, target, 'beforeChange');

    return target;
};

Then to use it:

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'

In your case, you could probably use something like this:

function TableCell(value) {
    this.value = ko.observable(value).extend({ previousValue: 'previousValue' });
    this.cssClass = ko.puted(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);
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论