HTML table not responding to Knockout binding
Asked Answered
C

1

1

I have a set of parent and child objects which I am displaying in a table. enter image description here

The table DOM is wired to the model via Knockout. This works pretty well and the table changes whenever the model changes.

Now, applying DataTable to the table brings in some issues to the table. The view is no longer responding to Knockout bindings for some reason.

You can see the problem illustrated in this jsFiddle

Click on 'Clear families' nothing will happen. I was expecting the table to completely clear out.

QUESTION

Why is the DOM no longer responding to my model changes?

Cornucopia answered 27/10, 2016 at 18:27 Comment(0)
D
1

It is because once you initialize data table to the DOM, DataTables takes control of the table by cloning and adds a number of elements around the table to both control the table and show additional information about it. So whenever you clear your array in fact your observableArray gets empty but it is out of control for knockout to update DataTable anymore. That's why when you click on add families back it gets added to view and then if you click on clear families those added rows only will be removed. DataTable was already initialized for loading data.

Solution: You need to modify your model in a way that can update DataTable as well. whenever you remove or add new item to you array you need to re-draw dataTable as well.

Assign a variable where you're initialing the table and either pass it as a parameter to your model or define it globally. Then inside your model whenever you remove or add a row update your dataTable as well.

var dt = $("#awesome-table").DataTable({"ordering": false});

 this.clearFamilies = function(){
      that.items.removeAll();
      // Update the table when All `items` array has been removed 
      dt.clear().draw();
      //Below will update the table whenever a single row is removed 
      // dt.row( rowIndexHere ).remove().draw();
 } 

to add also you need to re-draw the table inside your model like :dt.row.add( yourItemHere ).draw();

Alternative: If your table does not have a large data (performance doesn't have a role) you can take advantage of with binding around your table and allow it to be re-rendered with the new bindings. Check this out

I used a with binding which is set to null and then change that to the new data. This forces knockout to get rid of the DOM and automatically reapply the bindings when the with binding becomes non-null.

Details in this jsFiddle - Click on Add families and Remove families to see the magic happen :)

Darell answered 27/10, 2016 at 19:39 Comment(3)
Thanks a lot for the quick answer. I thought about adding rows using the table API but that will unfortunately not help as knockout won't see the new items and will therefore not bind to them.Cornucopia
Found a solution with your hints :) please see below and let me know what you think.Cornucopia
Awesome! Marked this one as the final answer :)Cornucopia

© 2022 - 2024 — McMap. All rights reserved.