for (var i = 0; i < 9; i++)
{
vm.icdCodes.push({Index:i, ID:'',DiagnosisCd: '' ,Description:ko.observable('')});
}
<tbody data-bind='foreach: $root.icdCodes'>
<tr>
<td>
<input type="text" class="icdCodeInput" list="icdcodes" data-bind="value: DiagnosisCd, event: { focusout: $root.dxCodeLostFocus}, attr: { id: 'icdCodeInput' + $index() }">
<datalist id="icdcodes" class="icdcodes">
</datalist>
<button type="button" class="btn btn-default btn-lg" data-bind=" click: $root.moveDxCodeUp, attr: { id: 'dxCodeUpButton' + $index() }">
<i class="icon-arrow-up"></i>
</button>
</td>
</tr>
</tbody>
vm.moveDxCodeUp = function (data) {
if (data.DiagnosisCd != "")
{
var currentDxCode = data;
var previousDxCode = vm.icdCodes()[data.Index - 1];
if (currentDxCode.Index > 0)
{
vm.icdCodes()[data.Index - 1] = currentDxCode;
vm.icdCodes()[data.Index] = previousDxCode;
var tempIndex = currentDxCode.Index;
currentDxCode.Index = previousDxCode.Index;
previousDxCode.Index = tempIndex;
}
}
In my HTML I am looping within icdCodes observable array to add few HTML 5 datalist and adjacent buttons alongside it. The button when clicked allows me to move the value in the current textbox into the textbox which is above it. The first time I click the button, the values gets interchanged properly. But if I hit the button again, the data parameter in the movedxCodeUp function still gets the original value (before the interchange) and not the value which got interchanged after hitting the button. I am also interchanging the values in the actual observable collection (icdCodes) in the function.
Even if your icdCodes
is a ko.observableArray
becuase you are directly manipulating the underlying array to swap your items KO won't be notified about this changes so it doesn't re-render the view.
To make it work you just need to call the valueHasMutated
function which notifies KO that your array has changed:
vm.icdCodes()[data.Index - 1] = currentDxCode;
vm.icdCodes()[data.Index] = previousDxCode;
vm.icdCodes.valueHasMutated();
Demo JSFiddle.