Reputation: 1951
I am using this plugin http://www.joshbuckley.co.uk/2011/07/knockout-js-datatable-bindings/ to handle datatables / ko bindings. Here's JS code:
function ProductViewModel() {
// Init.
var self = this;
self.products = ko.observableArray();
self.singleProduct = ko.observable();
var mappedProducts;
// At first load i'm loading data.
$.getJSON("/admin/test", function(allData) {
mappedProducts = $.map(allData, function(item) {
var p = new Product(item);
// I'm adding a new property to my model, to handle row level actions.
// I'm not sure this is a good practice.
p.edit = "<button data-bind='click: $root.edit'><i class='icon-pencil'></i></button>";
return p;
});
self.products(mappedProducts);
});
// Here i'm using the basic switch pattern, as from KO tutorials.
self.edit = function(product) {
console.log(product); // <--- Prints the whole self.products() array
self.singleProduct(product);
self.products(null);
}
self.list = function() {
self.products(mappedProducts);
self.singleProduct(null);
}
}
// My model.
function Product(item) {
this.name = ko.observable(item.name);
this.dealer = ko.observable(item.dealer);
this.cost = ko.observable(item.cost);
this.price = ko.observable(item.price);
this.picture = ko.observable();
}
Here's my markup:
<table id="products-table" class="table table-striped table-bordered table-hover"
data-bind="dataTable: {data: $parent.products, options: {aoColumns: [
{ bSortable: false, mDataProp: null, sDefaultContent: '' },
{mData: 'name'},
{mData: 'dealer'},
{mData: 'cost'},
{mData: 'price'},
{ bSortable: false, mData: 'edit' }
]}}">
<thead>
<tr>
<th>Pic</th>
<th>Name</th>
<th>Dealer</th>
<th>Cost</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody></tbody>
</table>
I am able to virtually switch between list and edit views, bindings seems to be properly handled.
Problem: when in the edit handler, i would expect to receive a single model as an argument; i am receiving the whole collection though, so i am not able to identify the model to edit.
One more thing: I am not sure at all this is a good practice of binding events on the rows, so any suggestion would be appreciated!
Upvotes: 1
Views: 4073
Reputation: 1951
Well i think i got it myself and reason is quite clear after peeking the plugin source code.
From plugin source:
(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);
Basically, for each update operation table is cleaned up and built again with the observable array, which should provide binding features.
What KO is trying to do, in each native click: binding, is to pass in the contextual data, which is the whole array, to the proper handler.
Upvotes: 1