Radio input knockout observable Array loses control after splicing

Enter radio input inside element multiplied by foreach knockout .

Give the observable array to this foreach.

Make a function to switch two of these items.

HTML:

<!-- ko foreach: boxes -->
<div>
  <!-- ko text: $data --><!-- /ko -->:
  <label><input type=radio value=apple data-bind="attr: { name: 'fruit-' + $index() }">apple</label>
  <label><input type=radio value=banana data-bind="attr: { name: 'fruit-' + $index() }">banana</label>
</div>
<!-- /ko -->
<button data-bind="click: switchBoxes">switch</button>

      

JS:

var viewModel = function () {
    this.boxes = ko.observableArray(['First', 'Second']);

  this.switchBoxes = function () {
    this.boxes.splice(0, 2, this.boxes()[1], this.boxes()[0]);
  };
};

ko.applyBindings(new viewModel());

      

script: https://jsfiddle.net/hejdav/6dzg9hs8/17/

Now - check both radios, then switch. See? One of the radio stations loses its validation.

Any idea to prevent this?

One strange thing: the loss only occurs when both radios are checked.

+3


source to share


1 answer


Since you haven't bound a property checked

, the checked state is irrelevant to Knockout. I thought that simple observation and binding checked

would make Knockout keep everything in shape. Not so: you seem to have found a bug.

For some reason, Knockout doesn't set the new last item in the list correctly. I was able to fix this by adding a call valueHasMutated

to the checked

-bound observable for the last item in the blocks.



var viewModel = function() {
  this.boxes = ko.observableArray([{
    name: 'First',
    value: ko.observable('')
  }, {
    name: 'Second',
    value: ko.observable('')
  }]);

  this.switchBoxes = function() {
    const arr = this.boxes();

    this.boxes.splice(0, 2, arr[1], arr[0]);
    arr[1].value.valueHasMutated();
  };
};

ko.applyBindings(new viewModel());
      

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- ko foreach: boxes -->
<div>
  <!-- ko text: name -->
  <!-- /ko -->
  (
  <!-- ko text: value -->
  <!-- /ko -->):
  <label><input type=radio value=apple data-bind="attr: { name: 'fruit-' + $index() }, checked: value">apple</label>
  <label><input type=radio value=banana data-bind="attr: { name: 'fruit-' + $index() }, checked: value">banana</label>
</div>
<!-- /ko -->

<button data-bind="click: switchBoxes">switch</button>
      

Run code


+2


source







All Articles