Anton Riab
Anton Riab

Reputation: 498

View data binding in nested dynamic observableArray

I need to put observableArray with dynamic size inside observableArray and bind data to View.

View is render values from newData, but not update it in newData, when i edit it in View.

ko.applyBindings(new (function () {
  var self = this;
  self.lengthNewData  = ko.observable(2);
  self.newData  = ko.observableArray();

  self.AddDataStrings = function () {
    let newString = ko.observableArray();
    for(let i0 = 0; i0 < self.lengthNewData(); i0++)
      newString.push(i0);
    self.newData.push(newString);
  }

  self.SendData = function () {
    alert(ko.toJSON(self.newData));
  }
})());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<span data-bind="visible: !newData().length">Number of rows: <input data-bind="value: lengthNewData"/></span>
<input type="button" value="Add" data-bind="click: $root.AddDataStrings"/>
<input type="button" value="Send"  data-bind="visible: newData().length, click: $root.SendData"/><br>

<table>
  <tbody data-bind="foreach: newData">
    <tr data-bind="foreach: $data">
      <td><input data-bind="value: $data"/></td>
    </tr>
  </tbody>
</table>

https://jsfiddle.net/tvxyyzkp/6/

Push Add, edit it and push Send. Data was not modified!
Why and What need to change?

Upvotes: 3

Views: 93

Answers (1)

Tomalak
Tomalak

Reputation: 338148

There are two immediate mistakes in your code.

  1. You do not push observables into your newString. You should do:

    newString.push(ko.observable(i0));
    
  2. You bind your inputs to $data. $data contains the unwrapped data value, i.e. it's not observable. Bind to $rawData in such a setup.

This works:

ko.applyBindings(new(function() {
  var self = this;

  self.lengthNewData = ko.observable(2);
  self.newData = ko.observableArray();

  self.AddDataStrings = function() {
    let newString = ko.observableArray();
    for (let i0 = 0; i0 < self.lengthNewData(); i0++)
      newString.push(ko.observable(i0));
    self.newData.push(newString);
  }

  self.SendData = function() {
    alert(ko.toJSON(self.newData));
  }
})());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<span data-bind="visible: !newData().length">Number of rows: <input data-bind="value: lengthNewData"/></span>
<input type="button" value="Add" data-bind="click: AddDataStrings" />
<input type="button" value="Send" data-bind="visible: newData().length, click: SendData" /><br>

<table>
  <tbody data-bind="foreach: newData">
    <tr data-bind="foreach: $data">
      <td><input data-bind="value: $rawData" /></td>
    </tr>
  </tbody>
</table>


<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

Upvotes: 2

Related Questions