Jeffrey Yasskin
Jeffrey Yasskin

Reputation: 5692

How to make changes to $data propagate back to Knockout's view-model?

I've got the following code using Knockout.js to display an array of bools as a series of checkboxes:

<table>
  <tr data-bind="foreach: Array">
    <td><input type=checkbox data-bind="checked:$data"></td>
  </tr>
  <tr data-bind="foreach: Array">
    <td data-bind="text:$data"></td>
  </tr>
</table>
<button data-bind="click: toggle0">Toggle Element 0</button>

<script>
var simpleModel = {
  "Array" : ko.observableArray([ko.observable(false),
                                ko.observable(false),
                                ko.observable(true)]),
  "toggle0" : function() {
      simpleModel.Array()[0](!simpleModel.Array()[0]());
  }
};
ko.applyBindings(simpleModel);
</script>

If you look at http://jsfiddle.net/tP9Dm/3/, you can see that, while the checkboxes respond to changes in the view-model, the view-model doesn't respond to changes in the checkboxes.

According to https://groups.google.com/d/msg/knockoutjs/-dHpOg5ZBPI/1q4iqdTlKvUJ, it looks like $data is unwrapped by the foreach loop, so data-bind doesn't know to use it to update the model.

Clearly I can fix this by making the array contain objects instead of simple booleans, but that seems like it should be an unnecessary extra layer of indirection. Is there a simpler way to propagate changes back to the model?

Upvotes: 2

Views: 364

Answers (1)

Judah Gabriel Himango
Judah Gabriel Himango

Reputation: 60021

There doesn't seem to be a way to do this, because $data in this case is the unwrapped value.

Even setting up a click handler doesn't work, because the data sent to your handler is also unwrapped.

Bummer. Looks like the only way to do this is to wrap your observable into an object, another layer of indirection.

Upvotes: 1

Related Questions