Pickels
Pickels

Reputation: 34632

Knockout.js: Custom binding resetting the value

In the following code the idea is that if you fill in 'test' that this is considered invalid and shouldn't write the value to the observable. The problem I have is that my custom binding is somehow resetting the observable's value.

A working version of the code below: http://jsfiddle.net/6hcpM/1/

var underlying = ko.observable('foo');
var errors = ko.observableArray()
var isValid = ko.dependentObservable(function(){
    return errors().length === 0
});

var vm = {
    name : ko.dependentObservable({
        read : underlying,
        write : function(value){
            errors([]);

            if(value==='test'){
             errors([ 'Cant be test matey' ]);   
            };

            if(isValid()){
              underlying(value);
            };
        }
    })
};

vm.name.isValid = isValid;

ko.bindingHandlers.validateCss = {
    update: function(element, valueAccessor) {
       observable = valueAccessor();
       observable.isValid(); //this somehow causes the problem
    }
};

ko.applyBindings(vm);

Upvotes: 1

Views: 2225

Answers (1)

RP Niemeyer
RP Niemeyer

Reputation: 114792

Your validateCss binding creates a dependency to vm.name.isValid. When you write "test" to the field, errors is updated, which causes isValid to update, which triggers all of the bindings in the input's data-bind attribute to be re-evaluated. So, the value binding gets evaluated again and replaces the current value with the value from name (which is stored in underlying).

So, basically the value binding is running again based on isValid changing.

There are several ways that you could handle it. You could let underlying get updated every time and, if necessary, store a clean value elsewhere that only gets updated when it is valid.

You could also put your custom binding on a different element. For example, you could wrap your input in a span or div and put the binding on it. I assume that you want the validateCss binding to assign a CSS class when the value is invalid.

Upvotes: 2

Related Questions