Knockout observables and DataTables 1.10 (pre-beta) - feedback please!
Knockout observables and DataTables 1.10 (pre-beta) - feedback please!
allan
Posts: 63,489Questions: 1Answers: 10,470 Site admin
Hello all,
One of my goals with DataTables 1.10 was to have it support external helper libraries such as Knockout. I've just put together a little demo showing DataTables using Knockout - rows are added to the table and removed automatically as the contents of the `observableArray` are altered, and the cells for existing items as their values are changed.
http://datatables.net/dev/knockout/
This makes use of the observable aspect of Knockout only, not templates as well.
This is my first effort of using Knockout, so I'm reaching out to all the Knockout experts out there. Firstly, what do you think, and secondly how can it be improved?
Many thanks,
Allan
One of my goals with DataTables 1.10 was to have it support external helper libraries such as Knockout. I've just put together a little demo showing DataTables using Knockout - rows are added to the table and removed automatically as the contents of the `observableArray` are altered, and the cells for existing items as their values are changed.
http://datatables.net/dev/knockout/
This makes use of the observable aspect of Knockout only, not templates as well.
This is my first effort of using Knockout, so I'm reaching out to all the Knockout experts out there. Firstly, what do you think, and secondly how can it be improved?
Many thanks,
Allan
This discussion has been closed.
Replies
Here's an example of some patterns we follow on a pretty regular basis with 1.9:
- Use global observables to keep track of the currently selected id and if we're currently editing things
[code]
var selectedCustomerId = ko.observable(null);
var editable = ko.observable(false);
[/code]
- An example of the data for a row:
[code]
var Customer = function(data) {
var myself = this;
myself.id = ko.observable(data.id);
myself.name = ko.observable(data.name);
// See if this is currently selected
myself.selected = ko.computed(function() {
return myself.id() === selectedCustomerId();
});
// Select this if it isn't already selected
myself.toggleSelected = function() {
if (!myself.selected()) {
selectedCustomerId(myself.id());
}
else {
selectedCustomerId(null);
}
};
// Alias for the global editable flag within the row
myself.editable = editable;
};
[/code]
- In a fnCreatedRow callback, apply a binding of the model to the row something like the following:
[code]
var fnCreatedRow = function(nRow, customer) {
// When clicking on a row, toggle whether or not it is selected
// (Note that things outside of the table can change which customer is selected and the customer selected may not even be one that is represented in this particular table)
$(nRow).attr("data-bind", "click: toggleSelected, css: { rowSelected: selected() }");
ko.applyBindings(data, nRow);
};
[/code]
- In the data function for a name cell:
[code]
var mDataName = function(customer, type)
{
if (type === "set") {
return null;
}
// Use the initial value for sorting / type comparisons
if (type === "sort" || type === "type") {
return customer.name();
}
// Span showing text if not editable, input showing the value if editable
return '';
};
[/code]
It seems to be a bit of a trade-off since DataTables and Knockout can overlap a little bit, but I'm very interested to hear from yourself and anyone else on how I can improve this situation. I suspect we'll end up with multiple possible ways of combining the libraries.
Regards,
Allan
First off all, compliments!
I recently started exploring libraries as Knockout and CANJS etc.
What is the reason you have chosen KnockOut ?
Best regards,
Rene
Its the library that most people have asked about for integration with DataTables, in this category of library. The other one is Backbone.
My using Knockout here shouldn't be seen as me endorsing Knockout over any other library - as I said above, its my first use of Knockout. Ultimately it would be nice to support more of these libraries in DataTables - but I had to start somewhere.
I don't really want this conversation to be sidetracked into the pros and cons of each library - this is specifically about Knockout. I'm sure it would be possible to integrate CANJS as well - if you want to let others know how you get on with it, a new thread would be great.
Allan
[code]
// Code for defining a column
{
data: 'first()',
fnCreatedCell: function(nTd, sData, oData, iRow, iCol) {
sData.first.subscribe(function(val) {
dt.row( iRow ).invalidate();
});
}
}
[/code]
A beta will be released once documentation has been written, at which point a dedicated download will be made available.
This thread is specifically about the Knockout integration.
Allan
Allan
Could you open a new thread if you have any other questions about 1.10 which are not specifically about my Knockout example? We've deviated from the topic a little :-). More than happy to answer your questions - I was just hoping to get a bit more feedback about the Knockout integration in this thread.
Allan
In the example there is code like:
[code]...
$.each( [ 'first', 'last', 'age' ], function (i, prop) {
that[ prop ].subscribe( function (val) {
// Find the row in the DataTable and invalidate it, which
// will cause DataTables to re-read the data
var rowIdx = dt.column( 0 ).data().indexOf( that.id );
dt.row( rowIdx ).invalidate();
} );
} );
...
[/code]
But in the event that you sort or filter the datatable it does not work properly. How do we get the right row and invalidate it so that it is updated properly?
[code]
dt.column( 0, {order:'index'} )
[/code]
Allan
Allan
That's the key!
`.dataTable()` returns a chained jQuery object (so your `table` elements in a jQuery object). While `.DataTable()` returns a DataTables API object. You can use `.dataTable().api()` to also get an API instance.
This will be explained properly in the documentation that is yet to be written :-)
Allan
Thanks for flagging that error - that's one I knew about and had hoped to fix today, but the day has rather run away with me... There are a couple of errors in the API helper functions not calling correctly as well.
Allan
This is a step in the right direction :)
Will this work with Scroller as well?
Morten
Allan
I would like to contribute, and see how DataTables would take part with Knockout.js environment like this:
http://www.codeproject.com/Articles/706114/CRUD-with-Knockout-js-and-Templates-everywhere
Also, it would be fine to access objects like images, spans, ... and modify them instead of providing full cell content.
regards!
I've been working on some custom bindings of late that might, hopefully, come to being able to use Knockout templates with DataTables...
Allan
I have created binding handler for knockout that I based on datatables 1.10: https://gist.github.com/rosieks/8812216
Main advantage of it over your solution is except it use knockout model, it also use knockout data binding. This provide ability to create rich template for column, take advantage of Chrome knockout debugger, etc. Unfortunately I need to use private function _fnAjaxUpdateDraw (https://gist.github.com/rosieks/8812216#file-knockout-datatables-js-L166) in order to pass data from model to table. Could you advice me if is there any better way to do that?
One thing about calling _fnAjaxUpdateDraw - I think you need to pass the table's settings object into `_fnAjaxUpdateDraw ` as the first parameter.
Allan
I haven't tried this, but couldn't you just link it to knockout by overriding the AJAX key in the DataTable configuration as in this example?;
http://editor.datatables.net/examples/advanced/localstorage.html
Not sure if anyone saw this, but
https://github.com/divmgl/knockout.datatables/blob/a4f02dfa5afa1d8dbb5b13978a24075a26dcafb1/knockout.datatables.js
This appears to be code that works with Knockout 3.0 and DataTables 1.10-dev
I'm brand new to DataTables. I'm not a Knockout expert, but I've been using it for about a year and have created some complex bindingHandlers. (There are definitely people more savy with Knockout than I am.) That being said, I think something like this would fit better into a Knockout project:
The main reason I like this better is because it uses Knockout to populate the table and uses the template engine built into Knockout. (This allows for more robust templates)
There's only one problem... removing a row doesn't work. I'm researching why this is the case and how to resolve it. If I can get past that, I'll add options the the table initialization.
I'd love to hear some feed back from others.
Here's a plunk that shows this: http://plnkr.co/edit/2IU0ToKIow6nOfX7TUSB