Question

I'm using Knockout JS, and I'm trying to create a simple UI where a series of dropdowns are used to fire an action that is dependant on the value with a parameter.

e.g. if I have a page that gives details of two vehicles and I want to assign them to values from a dropdown.

What is the simplest way, using knockout to provide a parameter (to tell me whether it's vehicle one or vehicle two) and have the dropdown reset itself straight after selection.

I've tried the value binding computed observables, but I couldn't get the select to reset itself immediately after selection.

I tried using a standard function with javascript, and the bind function to pass in the parameter, but this didn't help.

http://jsfiddle.net/7U45W/ This is what I have so far, but I have two problems with it:

  1. Changing the value of the select doesn't seem to call the write function
  2. If I fiddle with it enough I can get it to call the write function but then I can't find a way (without resorted to pure DOM manipulation to set <select> box back to the first option.

NB I've tried two different ways to bind the updateAssignment function but neither of them seem to work.

Is this something which needs custom bindings or extended bindings? Or is there a simpler way that I'm missing?

Was it helpful?

Solution

I'm not sure about whether it's a nice UI (hard to navigate and make selections using the keyboard). That being said, this isn't hard to achieve. Since the read value will never change, we need to ensure that subscribers are notified (and thus update the bound DOM elements) when the write function is called, even though the read value hasn't changed since last time.

The old answer contained a solution using two observables and a manual subscription (which can be seen at http://jsfiddle.net/Emca9/). This edited answer (updated fiddle at http://jsfiddle.net/Emca9/1/) uses two observables, one of which is a writeable computed observable, since that was requested in the comments.

Bind the select element like the following:

<select data-bind="options: $parent.drivers,
                   optionsText: 'name',
                   value: selectedDriver,
                   optionsCaption: 'Select driver'">
</select>

In the write function of the computed observable, ensure that subscribers are notified, to ensure they the bindingHandlers update the DOM elements (i.e. the selected option).

function CarViewModel(data){
    var self = this;

    // ... removed other properties for brevity

    self.todaysDriver = ko.observable();
    self.selectedDriver = ko.computed({
        read: function(){
            return undefined;
        },
        write: function(newValue){
            if (newValue){
                self.todaysDriver(newValue);
                self.selectedDriver.notifySubscribers();
            }
        }
    });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top