24

I want to bind boolean value to select element using KO v2.1.0, but obviously it doesn't work as expected.

HTML code:

<select data-bind="value: state">
    <option value="true">On</option>
    <option value="false">Off</option>
</select>

JavaScript code:

var model = {
    state: ko.observable(false)
};

ko.applyBindings(model)

So I expect the select box goes to "Off" position with the initial value false but it was at "On". If I put state: ko.observable("false") it will be correct but that's not I wanted. Anyone know how to bind the boolean value to select box with KO?

Jsfiddle: https://jsfiddle.net/greenlaw110/Ajm58/

Syscall
  • 19,327
  • 10
  • 37
  • 52
Gelin Luo
  • 14,035
  • 27
  • 86
  • 139

4 Answers4

38

Here is an option that we explored for this one from this forum post:

ko.bindingHandlers.booleanValue = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var observable = valueAccessor(),
            interceptor = ko.computed({
                read: function() {
                    return observable().toString();
                },
                write: function(newValue) {
                    observable(newValue === "true");
                }                   
            });
        
        ko.applyBindingsToNode(element, { value: interceptor });
    }
};

So, we use a custom binding to inject a writeable computed observable between the UI and our view model. This is just an alternative to doing it directly in your view model.

Sample here: https://jsfiddle.net/rniemeyer/H4gpe/

Syscall
  • 19,327
  • 10
  • 37
  • 52
RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • this is the perfect solution to me! it changes the mechanism, not data – Gelin Luo May 10 '12 at 19:10
  • This seems like the perfect solution. The only question I have is, are there any "hidden dangers" to this method? Does it scale well if you have a large number of booleanValue bindings? In short, is there any reason you would _not_ want to use this method? – Josh Nov 08 '12 at 14:29
  • I don't feel that there are any hidden issues with using this technique. It does add an extra writeable computed observable between the actual model value and the binding, but that is fairly minor and is something you would have to do on the view model side otherwise anyways. – RP Niemeyer Nov 10 '12 at 13:56
  • You'll want to mention that the fiddle needs KO 2.3 to show the `
    ` data.  It was saved with KO 3.0.
    – vapcguy Feb 19 '15 at 04:45
8

This happens because the select is working with strings, and not booleans at any stage. You should try a ko.computed( ... ) value instead.

Check here for details: https://jsfiddle.net/Ajm58/3/

<select id="testSelect" data-bind="value: stateString">
    <option value="true">true</option>
    <option value="false">false</option>
</select>
​

var model = {
    state: ko.observable(false)
};

model.stateString = ko.computed({
    read: function() { return (this.state() ? "true" : "false"); },
    write: function(value) { this.state(value == "true"); }
}, model);

ko.applyBindings(model);


setTimeout(function() {
    model.state(true);    
}, 1500);

setTimeout(function() {
    $("#testSelect").val("false");
}, 3000);
Syscall
  • 19,327
  • 10
  • 37
  • 52
Owen Berry
  • 401
  • 3
  • 2
4

Much easier than the other answers: use the options-Binding.

The answer is in the kind of lengthy expression below:

<select data-bind="options: [{text: 'On', value: true}, {text: 'Off', value: false}], value: lala1, optionsValue: 'value', optionsText: 'text'">

By using the options binding, you're able to assign virtually everything to the value of an option. It's rather uncommon, I guess, to bind an explicit value to the options binding, but in this 2-way case, it is reasonable.

K. Rohde
  • 9,439
  • 1
  • 31
  • 51
3

I think I got the answer, put the number "1" and "0" to the option value respectively:

<select data-bind="value: state">
    <option value="1">On</option>
    <option value="0">Off</option>
</select>

See https://jsfiddle.net/greenlaw110/Ajm58/2/

Syscall
  • 19,327
  • 10
  • 37
  • 52
Gelin Luo
  • 14,035
  • 27
  • 86
  • 139
  • 1
    That does not bind as a boolean value, see [this fiddle](http://jsfiddle.net/Whw9S/). state actually equals '0' or '1' here, not true or false. – Jason Goemaat May 09 '12 at 22:19