JohnR90 JohnR90 - 3 months ago 8
Ajax Question

KnockoutJS select affecting observable in an unexpected way depending on when the select is created

This is the select:

<div class="pull-left" data-bind="if: existingPackagingLevels().length > 0 && activateSelect() == true">
<h4>Unique container</h4>
<select data-bind="enable: inUniqueContainerEditMode,
options: containers,
optionsText: function(container){ return container.name() + ' ' + container.type() },
optionsValue: 'id',
value: existingPackagingLevels()[0].uniqueContainerId,
optionsCaption: '--Select--'"></select>

<button data-bind="visible: inUniqueContainerEditMode() == false, click: editUniqueContainer"><i class="icon-pencil"></i></button>
<button data-bind="visible: inUniqueContainerEditMode, click: saveNewUniqueContainer">save</button>
<button data-bind="visible: inUniqueContainerEditMode, click: cancelNewUniqueContainer">cancel</button>
</div>


I load the existingPackagingLevels variable with ajax. The first element in the array might or might not have a uniqueContainerId. I want to display the selected container when existingPackagingLevels[0].uniqueContainerId() != undefined or to show the "--Select--" option otherwise.

The problem: when I let the select be created only after passing this check:

<div class="pull-left" data-bind="if: existingPackagingLevels().length > 0">


The select basically overwrites my existingPackagingLevels[0].uniqueContainerId() and makes it undefined.
So I added the other check "activateSelect() == true" and that starts showing true after a delay I place. With a delay of 100ms it works half and half. Half the time it will overwrite the value and set it to undefined and half the time it will work as expected and show the container which corresponds to the uniqueContainerId. With a greater delay it will work all of the time.

So how do I make it work without delaying it with trickery?

Answer

Try the valueAllowUnset parameter.

Normally, when you use the value binding on a <select> element, it means that you want the associated model value to describe which item in the <select> is selected. But what happens if you set the model value to something that has no corresponding entry in the list? The default behavior is for Knockout to overwrite your model value to reset it to whatever is already selected in the dropdown, thereby preventing the model and UI from getting out of sync.

However, sometimes you might not want that behavior. If instead you want Knockout to allow your model observable to take values that have no corresponding entry in the <select>, then specify valueAllowUnset: true. In this case, whenever your model value cannot be represented in the <select>, then the simply has no selected value at that time, which is visually represented by it being blank. When the user later selects an entry from the dropdown, this will be written to your model as usual.

Comments