I have a plunk that demonstrates my issue: http://plnkr.co/edit/PzBrcTX0Vnn01xWy4dk6
This is a table that has a list of "settings". It uses Footable so the list can be sorted and other features of Footable.
Scenario 1: run, push the remove setting button for one or more rows. Notice that the row is removed after the buttons is pushed. This is the expected behavior.
Scenario 2: run, click on the setting column header and ensure that the column is sorted, push the remove button. Notice that the row is not removed from the view.
If you put a break point in ApplicationSettings.js:
var removeItem = function (item) {
items.remove(item);
};
You can see that in both scenarios the observable array is removing the items as expected, but in scenario 2 the view is not updated as expected.
The issue comes from the empty text nodes that surround each <tr>
element. The foreach
binding also tracks those text nodes. See https://github.com/knockout/knockout/pull/709 for a discussion about why it's not possible to just ignore them as a general rule. On the other hand, your custom binding can strip them out.
See how knockout-sortable does this (for similar reasons):
var nodes = Array.prototype.slice.call(element.childNodes, 0);
ko.utils.arrayForEach(nodes, function(node) {
if (node && node.nodeType !== 1) {
node.parentNode.removeChild(node);
}
});
You need to make sure this is run before foreach
. I modified your binding to do that: http://plnkr.co/edit/hS6Gb2xLfabSj9K8l03y?p=preview