Bindings In KnockoutJS - Part IV

In this Part IV, we will explain bindings for form elements.

Part III explained some of the bindings available for form elements. In this Part IV, we will explain the bindings for the form elements. 

The bindings that we will discuss in this part are:
  1. checked binding
  2. click binding
  3. event binding
  4. hasFocus binding
  5. options binding
  6. selectedOptions binding
Let us discuss the bindings one by one.

The Checked Binding

The checked binding updates the true/false value into the associated viewmodel property based on control state. Likewise, it changes the state of the control [check-box, radio button] as checked/unchecked based on the viewmodel property's value.

<div data-bind="with: checkedBinding">

    Select the fruit:

    <div<input type="radio" value="Apple" name="checkedgroup" data-bind="checked: checkedValue" /><span data-bind="style: { color:           checkedValue() === 'Apple' ? 'Green' : '' }"> Apple </span</div>

    <div<input type="radio" name="checkedgroup" value="Orange" data-bind="checked: checkedValue" /><span data-bind="style: { color:         checkedValue() === 'Orange' ? 'Green' : '' }"> Orange </span</div>

    <div<input type="radio" name="checkedgroup" value="Banana" data-bind="checked: checkedValue" /><span data-bind="style: { color:         checkedValue() === 'Banana' ? 'Green' : '' }"> Banana </span</div>

    <p<input type="text" data-bind="value: isChecked, valueUpdate: 'keyup'" />Type the fruit name to select </p>

</div>


The checkedValue viewmodel property is bound with the input element (radio button) and will change the state of the radio button to checked/unchecked based on whether the property value is equal to the radio button's value. When you start selecting the radio button, the selected radio button's text will be changed to green and the fruit name will be updated into the text-box. Likewise, type the Fruit name into the text box given, the corresponding radio button will be selected.

Note: The radio button will be selected only if the checkedValue proeprty's value is equal to the radio button's value.

The Click Binding

The click binding adds an event handler to the associated DOM and executes the bound viewmodel function when the DOM is clicked. We can use the click binding with all the elements.

<div data-bind="with: clickBinding">

    <p><b>Click binding</b></p>

    <p<input data-bind="checked: isBubbling" type="checkbox" />Make inner Div to bubble the Click event?</p<p>

        <div class="outer" data-bind="click: function (data, event) { divClicked(data, event); }">

            <div class="inner" data-bind="click: clickMe, clickBubble: isBubbling()">Inner Div - Click Me </div>

        </div>

    </p>

</div>


In this above example, we have two divs and a check-box. When the check-box is checked and if you click on the inner div then the click event will be fired and the event will be bubbled to the parent. The clickBubble binding accessor accepts the true/false value and will let the click event bubble up to the parent. When you check the check-box, the isBubbling property will be updated with true; since isBubbling is true, the clickBubble binding handler makes the click event bubble up to the parent.

Note: Here the checked binding updates the property with element's state (true/false) value whereas if you use checked with radio button, it updates the property with the elements value but not state.

The Event Binding

The event binding adds an event handler for the specific event you mentioned and executes the bound viewmodel function when the specific event is triggered for the associated DOM element.

<div data-bind="with: eventBinding">

    <p><b>Event binding</b></p>

    <p<input data-bind="checked: isBubbling" type="checkbox" />Make inner Div to bubble the Click event? </p>

    <p>

        <div class="outer" data-bind="event: { mousedown: function (data, event) { divClicked(data, event); } }">

            <div class="inner" data-bind="event: { mousedown: clickMe }, mousedownBubble: isBubbling()">Inner Div - Click Me </div>

        </div>

    </p>

</div>


The same example for the clicked event is used here except the click binding handler. Instead of using click binding handler, we use the event binding handler so that we can add the event handlers for the events that we need to add. In this  example, we have added a mousedown event.

Note: the mousedownBubble binding handler can be clickBubble for click event or keyupBubble for keyup event. The convention is eventnameBubble.

The HasFocus Binding 

The hasFocus binding updates the focus state of the associated element into the bound viewmodel property. Likewise, the viewmodel property's value will update the focus state of the element.

<div data-bind="with: formBinding">

    <p><b>HasFocus/Checked binding</b></p>

    <p<input data-bind="checked: isDisabled" type="checkbox" />Disable the submit button </p>

    <form data-bind="submit: submitMe">

        <pName: <input type="text" data-bind="value: text, valueUpdate: 'keyup', hasFocus: hasTextboxFocused" />Type something to enable             submit button </p>

        <button type="submit" data-bind="enable: isEnabled">Submit</button>

        <button data-bind="click: function () { hasTextboxFocused(true); }, disable: hasTextboxFocused()">Focus Textbox</button>

    </form>

</div>


In the example above, the viewmodel property "hasTextBoxFocused" is bound with the text input element. When the TextBox is focused, the "Focus Textbox" button is disabled as the "hasTextboxFocused" property is bound with the button's disable binding handler.

The Options Binding

The options binding is used with the "select" element when you want to render a single-select dropdown list. The options binding adds the items to the select element and the value assigned to the binding should be the array or observableArray.

    <p><b>Options Binding</b></p>

    <pSelect an Item:

    <select class="single" data-bind="

options: items,

optionsText: 'name',

optionsValue: 'id',

value: selectedItem, 

optionsCaption: 'Select...'

optionsAfterRender: fadeInOptions">

    </select</p>

    <div data-bind="visible: selectedItem, with: selectedItem">

        You have selected <span data-bind="text: $data, style: { background: $data }"></span>.

    </div>

Here, we have bound the items observableArray that has an array of the Item class. The Item class has two properties, name and id. The name property is a string and the id is the number for the name. 
  • the value for the options binding handler should be an array or observableArray that has the values for option.  
  • The optionsText binding accessor says the select element on which the property's value should display as the option's text. In this example, its name property.
  • The optionsValue binding accessor says the select element on which property's value should be set as value of the option. In this example, its id property.
  • The value binding handler updates the associated property with the value of selected option in the dropdown list.
  • The optionCaption accessor sets the caption for the dropdown list.
  • The optionsAfterRender accessor is a callback that will be executed after each option in the array is rendered.
If you select any option then, based on the selection, the text color and selected text will be displayed as per the markup.

The SelectedOptions Binding

The selectedOptions binding can be used when you want to render a multi-select dropdown list. The selectedOptions binding will update the selected options into the bound observableArray.

<p><b>SelectedOptions Binding</b></p>

    <pSelect Items:

    <select class="multi" data-bind="

options: items, 

optionsText: 'name'

selectedOptions: selectedItems" size="5" multiple="true">

    </select>

    </p<p>selectedItems observableArray has: </p<pre data-bind="text: ko.toJSON(selectedItems(), null, 2)"></pre>


Here, the selectedOptions binding accessor will update the bound viewmodel property with the selected options data. If the value bound with the options binding is an array of strings or a number then you don't want to add the optionsText binding accessor else if the options value is an observableArray or array of objects then you need to set the optionsText binding accessor with the viewmodel's property name so that it displays the value from the object's proeprty on the drop down list.

We have discussed all of the bindings available for form elements. The complete example with source is available below.