Nico Beemster
Nico Beemster

Reputation: 590

JQuery DataTables + KnockOut (+ BootStrap) bug?

I have bound a KnockOut observableArray to a jQuery DataTable. When I dynamically add items to this array, the new items are correctly being rendered in the table, however some options of the datatable itself are not being refreshed. The pager doesn't get updated. Also the "no data available" message does not disappear.

HTML:

<table class="table table-striped" id="tblSample">
    <thead>
        <tr>
            <th>Name</th>
        </tr>
    </thead>

    <tbody data-bind="foreach: List">
        <tr>
            <td data-bind="text: Name"></td>
        </tr>
    </tbody>
</table>
<button class="btn" type="button" data-bind="click: AddSample">Test</button>

Knockout model:

var Sample = function(name) {
    this.Name = ko.observable(name);
};

var ViewModel = function() {
    var self = this;
    self.List = ko.observableArray();
    self.AddSample = function() {
        self.List.push(new Sample('New'));
    };
};

ko.applyBindings(new ViewModel());​

DOM ready:

$(document).ready(function() {

    $('#tblSample').dataTable({
        "sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
        "sPaginationType": "bootstrap",
        "bFilter": true,
        "bLengthChange": false,
        "bSort": true,
        "iDisplayLength": 15,
        "oLanguage": {
            "sLengthMenu": "_MENU_ records per pagina"
        }
    });
});

Working JSFiddle: http://jsfiddle.net/PhpDk/1

Am I doing something wrong, or is this a bug?

Thanks, Nico

(edit: fixed CDN links in jsfiddle)

Upvotes: 2

Views: 4757

Answers (2)

Zach Painter
Zach Painter

Reputation: 140

This is the way to do it... I have made a jsfiddle showing this:

To get this to work I had to add two callback methods to the original knockout foreach binding definition. I am currently trying to get these events into the newest version of knockout. I needed to add a beforeRenderAll and afterRenderAll callback to destroy the datatable and reinitialize the datatable after the knockouts foreach binding adds the html. This works like a charm The JSFiddle showing this has a fully editable jquery datatable bound to the ViewModel through knockout.

ko.bindingHandlers.DataTablesForEach = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        var value = ko.unwrap(valueAccessor()),
        key = "DataTablesForEach_Initialized";

        var newValue = function () {
            return {
                data: value.data || value,
                beforeRenderAll: function(el, index, data){
                    if (ko.utils.domData.get(element, key)) {                                   
                        $(element).closest('table').DataTable().destroy();
                    }
                },
                afterRenderAll: function (el, index, data) {
                    $(element).closest('table').DataTable(value.options);
                }

            };
        };

        ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext);

        //if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized
        if (!ko.utils.domData.get(element, key) && (value.data || value.length)) {
            ko.utils.domData.set(element, key, true);
        }

        return { controlsDescendantBindings: true };
}

};

jsfiddle w/ bootstrap

Upvotes: 1

Anders
Anders

Reputation: 17554

There is a native knockout grid called KoGrid https://github.com/ericmbarnard/KoGrid

But if you really want to use Datatables there is a ready to go knockout binding for it (It works with 1.9.0 only)

I have forked that binding on Github and extended it somewhat (You can access Datables object from ViewModel to refresh, filter, sort, etc), you can find it here

https://github.com/AndersMalmgren/Knockout.Extensions

Upvotes: 2

Related Questions