I am currently using Josh Buckley's Datatables binding for Knockout. I'm trying to create a "delete row" button in the datatable. I currently have a click data-bind on each button. The datatable source is hooked up to an observable array. When a user clicks on the button, the object is removed from the observable array, which then triggers the update binding, and the table view subsequently gets updated. That all works fine, at least the first time I click on a button.
However, once the the table is updated, all of the click bindings on the "delete row" buttons stop working. I presume that this is because the entire table is cleared and rebuilt each time the update binding is called, and so the bindings aren't applied on the new elements.
How can I rebind the new elements that are generated with each datatable update? Alternatively, is there a better way to handle this?
Custom binding:
(function($){
ko.bindingHandlers.dataTable = {
init: function(element, valueAccessor){
var binding = ko.utils.unwrapObservable(valueAccessor());
// If the binding is an object with an options field,
// initialise the dataTable with those options.
if(binding.options){
$(element).dataTable(binding.options);
}
},
update: function(element, valueAccessor){
var binding = ko.utils.unwrapObservable(valueAccessor());
// If the binding isn't an object, turn it into one.
if(!binding.data){
binding = { data: valueAccessor() }
}
// Clear table
$(element).dataTable().fnClearTable();
// Rebuild table from data source specified in binding
$(element).dataTable().fnAddData(binding.data());
}
};
})(jQuery);
HTML code:
<table id="membersTable" class="table table-striped table-bordered bootstrap-datatable datatable" data-bind="dataTable: membersTable">
<thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
</table>
View Model:
var groupViewModel = {
groupMembers: ko.observableArray([
new GroupMember("1", "Abe", true),
new GroupMember("2", "Bob", false),
new GroupMember("3", "Bill", false)
])
};
groupViewModel.membersTable = ko.computed(function() {
var self = this;
var final_array = new Array();
for(var i = 0; i < self.groupMembers().length; i++)
{
var row_array = new Array();
row_array[0] = self.groupMembers()[i].nameWithLink();
row_array[1] = self.groupMembers()[i].actions();
final_array.push(row_array);
}
return final_array;
}, groupViewModel);
groupViewModel.removeMember = function(id) {
var self = this;
self.groupMembers.remove(function(groupMember) {
return groupMember.id == id;
});
};
Group Member object:
function GroupMember(id, name, isGroupLeader)
{
var self = this;
self.id = id;
self.name = name;
self.isGroupLeader = ko.observable(isGroupLeader);
self.link = ko.computed(function() {
return "/#user/" + self.id;
});
self.nameWithLink = ko.computed(function() {
return '<a href="' + self.link() + '">' + self.name + '</a>';
});
self.actions = ko.computed(function() {
return '<a class="btn btn-danger" data-bind="click: function() {removeMember(' + self.id + ')}">' + '<i class="icon-minus-sign"></i>' + '</a>';
});
}
Edit:
jsfiddle link: http://jsfiddle.net/zongweil/PLUKv/1/