Leonardo
Leonardo

Reputation: 11401

Knockout -> Bind element to Value of Select

In the following select, I'm binding an observable array.

<select id="selectProtocols" data-bind="options: optionsAvailable, optionsCaption:'Selecione...', optionsText: 'SimpleDescription', optionsValue:'???'"></select>

I believe it's easy to see that that the text of each option is a property "SimpleDescription", that works fine. What I need now is that the value of the select is the element itself!

How can I do that?

Upvotes: 0

Views: 330

Answers (4)

connexo
connexo

Reputation: 56803

Note 2: Working with drop-down lists (i.e., <select> elements)

Knockout has special support for drop-down lists (i.e., <select> elements). The value binding works in conjunction with the options binding to let you read and write values that are arbitrary JavaScript objects, not just string values. This is very useful if you want to let the user select from a set of model objects. For examples of this, see the options binding or for handling multi-select lists, see the documentation for the selectedOptions binding.

http://knockoutjs.com/documentation/value-binding.html

Upvotes: 1

Leonardo
Leonardo

Reputation: 11401

I ended up using the optionsValue:$data combined with optionsAfterRender function... it worked as expected with the object being passed around "in-natura"!

Upvotes: 0

300 baud
300 baud

Reputation: 1672

Simply do not set the optionsValue attribute and Knockout will automatically store the selected object from the observableArray into the observable you have declared in the value attribute.

Deep within the bowels of Knockout is the following function:

function applyToObject(object, predicate, defaultValue) {
    var predicateType = typeof predicate;
    if (predicateType == "function")    // Given a function; run it against the data value
        return predicate(object);
    else if (predicateType == "string") // Given a string; treat it as a property name on the data value
        return object[predicate];
    else                                // Given no optionsText arg; use the data value itself
        return defaultValue;
}

If you do not set the optionsValue attribute then this function will fall into the bottom else statement which will return the current array item.

Upvotes: 1

Milimetric
Milimetric

Reputation: 13549

Assigning $data to optionsValue does not make sense here, you have to read what optionsValue does [1]. It basically just sets the value attribute of the <option> elements under your <select>. So you can't set it to the JS object that's being selected, you can only set it to text.

<select data-bind="
    options: optionsAvailable,
    optionsCaption: 'Selecione...',
    optionsText: 'SimpleDescription',
    optionsValue: 'SomeOtherPropertyThatEvaluatesToText',    
    value: selectedOption"></select>

The value binding should receive an observable that will be set to the selected JS object. And, if you want, you can give optionsValue a function that takes this JS object and turns it into text, like this:

<select data-bind="
    options: optionsAvailable,
    optionsCaption: 'Selecione...',
    optionsText: 'SimpleDescription',
    optionsValue: JSON.stringify,    
    value: selectedOption"></select>

Here's a sample fiddle to play with: http://jsfiddle.net/43t9dzxt/1/

[1] http://knockoutjs.com/documentation/options-binding.html

Upvotes: 1

Related Questions