The options binding
The options
binding controls what options should appear in a drop-down list (i.e., a <select>
element) or multi-select list (e.g., <select size='6'>
). This binding cannot be used with anything other than <select>
elements.
The value you assign should be an array (or observable array). The <select>
element will then display one item for each item in your array.
Tip
For a multi-select list, to set which of the options are selected, or to read which of the options are selected, use the selectedOptions binding. For a single-select list, you can also read and write the selected option using the value binding.
Examples¶
Drop-down list
<p> Destination country: <select data-bind="options: availableCountries"></select> </p>
var viewModel = { // These are the initial options availableCountries: fw.observableArray(['France', 'Germany', 'Spain']) }; // ... then later ... viewModel.availableCountries.push('China'); // Adds another option
Multi-select list
<p> Choose some countries you would like to visit: <select data-bind="options: availableCountries" size="5" multiple="true"></select> </p>
var viewModel = { availableCountries: fw.observableArray(['France', 'Germany', 'Spain']) };
Drop-down list representing arbitrary JavaScript objects, not just strings
<p> Your country: <select data-bind="options: availableCountries, optionsText: 'countryName', value: selectedCountry, optionsCaption: 'Choose...'"></select> </p> <div data-bind="visible: selectedCountry"> <!-- Appears when you select something --> You have chosen a country with population <span data-bind="text: selectedCountry() ? selectedCountry().countryPopulation : 'unknown'"></span>. </div>
// Constructor for an object with two properties var Country = function(name, population) { this.countryName = name; this.countryPopulation = population; }; var viewModel = { availableCountries : fw.observableArray([ new Country("UK", 65000000), new Country("USA", 320000000), new Country("Sweden", 29000000) ]), selectedCountry : fw.observable() // Nothing selected by default };
Drop-down list representing arbitrary JavaScript objects, with displayed text computed as a function of the represented item
<!-- Same as previous example, except the <select> box expressed as follows: --> <select data-bind="options: availableCountries, optionsText: function(item) { return item.countryName + ' (pop: ' + item.countryPopulation + ')' }, value: selectedCountry, optionsCaption: 'Choose...'"></select>
Parameters¶
-
Main parameter: You should supply an array (or observable array). For each item, Footwork will add an
<option>
to the associated<select>
node. Any previous options will be removed.-
If your parameter's value is an array of strings, you don't need to give any other parameters. The
<select>
element will display an option for each string value. However, if you want to let the user choose from an array of arbitrary JavaScript objects (not merely strings), then see theoptionsText
andoptionsValue
parameters below. -
If this parameter is an observable value, the binding will update the element's available options whenever the value changes. If the parameter isn't observable, it will only set the element's available options once and will not update them again later.
-
-
Additional parameters
-
optionsCaption
Sometimes, you might not want to select any particular option by default. But a single-select drop-down list usually starts with some item selected, so how can you avoid preselecting something? The usual solution is to prefix the list of options with a special dummy option that just reads "Select an item" or "Please choose an option" or similar, and have that one selected by default.
This easy to do: just add an additional parameter with name
optionsCaption
, with its value being a string to display. For example:<select data-bind='options: myOptions, optionsCaption: "Select an item...", value: myChosenValue'></select>
Footwork will prefix the list of items with one that displays the text "Select an item..." and has the value
undefined
. So, ifmyChosenValue
holds the valueundefined
(which observables do by default), then the dummy option will be selected. If theoptionsCaption
parameter is an observable, then the text of the initial item will update as the observable's value changes. -
optionsText
See Example 3 above to see how you can bind
options
to an array of arbitrary JavaScript object - not just strings. In this case, you need to choose which of the objects' properties should be displayed as the text in the drop-down list or multi-select list. Example 3 shows how you can specify that property name by passing an additional parameter calledoptionsText
.If you don't want to display just a simple property value as the text for each item in the dropdown, you can pass a JavaScript function for the
optionsText
option and supply your own arbitrary logic for computing the displayed text in terms of the represented object. See Example 4 above, which shows how you could generate the displayed text by concatenating together multiple property values. -
optionsValue
Similar to
optionsText
, you can also pass an additional parameter calledoptionsValue
to specify which of the objects' properties should be used to set thevalue
attribute on the<option>
elements that Footwork generates. You can also specify a JavaScript function to determine this value. This function will receive the selected item as its only argument and should return a string to use for the<option>
element's value attribute.Typically you'd only want to use
optionsValue
as a way of ensuring that Footwork can correctly retain selection when you update the set of available options. For example, if you're repeatedly getting a list of "car" objects via Ajax calls and want to ensure that the selected car is preserved, you might need to setoptionsValue
to"carId"
or whatever unique identifier each "car" object has, otherwise Footwork won't necessarily know which of the previous "car" objects corresponds to which of the new ones. -
optionsIncludeDestroyed
Sometimes you may want to mark an array entry as deleted, but without actually losing record of its existence. This is known as a non-destructive delete. For details of how to do this, see the destroy function on
observableArray
.By default, the options binding will skip over (i.e., hide) any array entries that are marked as destroyed. If you want to show destroyed entries, then specify this additional parameter like:
<select data-bind='options: myOptions, optionsIncludeDestroyed: true'></select>
-
optionsAfterRender
If you need to run some further custom logic on the generated
option
elements, you can use theoptionsAfterRender
callback. See Note 2 below. -
selectedOptions
For a multi-select list, you can read and write the selection state using
selectedOptions
. Technically this is a separate binding, so it has its own documentation. -
valueAllowUnset
If you want Footwork to allow your model property to take values that have no corresponding entry in your
<select>
element (and display this by making the<select>
element blank), then see documentation forvalueAllowUnset
.
-
Notes¶
Selection is preserved when setting/changing options
When the options
binding changes the set of options in your <select>
element, Footwork will leave the user's selection unchanged where possible. So, for a single-select drop-down list, the previously selected option value will still be selected, and for a multi-select list, all the previously selected option values will still be selected (unless, of course, you've removed one or more of those options).
That's because the options
binding tries to be independent of the value
binding (which controls selection for a single-select list) and the selectedOptions
binding (which controls selection for a multi-select list).
Post-processing the generated options
If you need to run some further custom logic on the generated option
elements, you can use the optionsAfterRender
callback. The callback function is invoked each time an option
element is inserted into the list, with the following parameters:
-
The inserted
option
element -
The data item against which it is bound, or
undefined
for the caption element
Here's an example that uses optionsAfterRender
to add a disable
binding to each option.
<select size="3" data-bind=" options: myItems, optionsText: 'name', optionsValue: 'id', optionsAfterRender: setOptionDisable"> </select>
var vm = { myItems: [ { name: 'Item 1', id: 1, disable: fw.observable(false)}, { name: 'Item 3', id: 3, disable: fw.observable(true)}, { name: 'Item 4', id: 4, disable: fw.observable(false)} ], setOptionDisable: function(option, item) { fw.applyBindingsToNode(option, {disable: item.disable}, item); } }; fw.applyBindings(vm);