Knockoutjs custom binding are executed before items are fully rendered

前端 未结 2 777
不知归路
不知归路 2021-01-28 13:42

I\'m trying to execute callback on list of items to make pagination using DataTable. Now i want to execute my callback after all my items have been rendered not after each item

相关标签:
2条回答
  • 2021-01-28 14:06

    Here is a custom binding that I use! This covers any datatables options that you want to define in the binding...

    ko.bindingHandlers.dataTablesForEach = {
    page: 0,
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
      var options = ko.unwrap(valueAccessor());
      ko.unwrap(options.data);
      if(options.dataTableOptions.paging){
        valueAccessor().data.subscribe(function (changes) {
            var table = $(element).closest('table').DataTable();
            ko.bindingHandlers.dataTablesForEach.page = table.page();
            table.destroy();
        }, null, 'arrayChange');         
      }
        var nodes = Array.prototype.slice.call(element.childNodes, 0);
        ko.utils.arrayForEach(nodes, function (node) {
            if (node && node.nodeType !== 1) {
                node.parentNode.removeChild(node); 
            }
        });
        return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {       
        var options = ko.unwrap(valueAccessor()),
            key = 'DataTablesForEach_Initialized';
        ko.unwrap(options.data);
        var table;
        if(!options.dataTableOptions.paging){
          table = $(element).closest('table').DataTable();
            table.destroy();
        }
        ko.bindingHandlers.foreach.update(element, valueAccessor, allBindings, viewModel, bindingContext);
        table = $(element).closest('table').DataTable(options.dataTableOptions);
        if (options.dataTableOptions.paging) {
           if (table.page.info().pages - ko.bindingHandlers.dataTablesForEach.page == 0)
               table.page(--ko.bindingHandlers.dataTablesForEach.page).draw(false);               
           else
               table.page(ko.bindingHandlers.dataTablesForEach.page).draw(false);               
        }       
        if (!ko.utils.domData.get(element, key) && (options.data || options.length))
            ko.utils.domData.set(element, key, true);
        return { controlsDescendantBindings: true };
    }
    };
    

    JSFIDDLE

    0 讨论(0)
  • 2021-01-28 14:07

    From a logical point of view, shouldn't the ConvertToDataTable binding be on the table itself, instead on the foreach?

    Also, shouldn't you control table layout via the binding or the view model? The custom binding is a very bad place for hard-coded values.

    Anyway, controlsDescendantBindings is your friend (docs):

    Custom Binding:

    ko.bindingHandlers.dataTable = {
        init: function () {
            return { controlsDescendantBindings: true };
        },
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var layout = valueAccessor();
    
            ko.applyBindingsToDescendants(bindingContext, element);
            $(element).dataTable({ "sDom": layout });
        }
    };
    

    View Model:

    {
        dataTableLayout: "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
        tasks: ko.observableArray([/* ... */])
    }
    

    Template:

    <table data-bind="dataTable: dataTableLayout">
        <thead>
            <tr>
                <td>Task Name</td>
                <td>Task Description</td>
            </tr>
        </thead>
        <tbody data-bind="foreach: tasks">
            <tr>
                <td data-bind="text: Name"></td>
                <td data-bind="text: Details"></td>
            </tr>
        </tbody>
    </table>
    

    http://jsfiddle.net/WcaM5/

    Disclaimer: I don't know exactly how jQuery DataTables work, so the sample is aircode. The point I want to make is that you can take manual control over the binding if necessary.

    0 讨论(0)
提交回复
热议问题