0

DataTableを使用してページネーションを作成するために、アイテムのリストでコールバックを実行しようとしています。各アイテムがレンダリングされた後ではなく、すべてのアイテムがレンダリングされた後にコールバックを実行したいと思います。そのSOの質問に続いて、単純なカスタムバインディングを作成しました

ko.bindingHandlers.ConvertToDataTable = {
    update: function (element, valueAccessor, allBindings) {
        var list = ko.utils.unwrapObservable(valueAccessor()); //grab a dependency to the obs array        
        var tableId = allBindings().tableId;
        $('#' + tableId).dataTable({
            "sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>"
        });
    }
}

私の見解は次のとおりです。

<table class="table table-striped table-bordered" data-bind="attr: { id: tableId }">
    <thead>
        <tr>
            <td>Task Name</td>
            <td>Task Description</td>
        </tr>
    </thead>
    <tbody>
        <!-- ko foreach: tasks, ConvertToDataTable: tasks, tableId: tableId -->
        <tr>
            <td data-bind="text: Name"></td>
            <td data-bind="text: Details"></td>
        </tr>
        <!-- /ko -->
    </tbody>
</table>

そのコードは正常に機能しますが、アイテムの数が少ないです。しかし、recoreds の数が多い場合 (たとえば 500)、アイテムが完全に更新される前にカスタム バインディングが実行されます。何かアイデアはありますか?

更新AJAX を介してサーバーからデータを取得するため、監視可能な配列が空である
間にカスタム バインディングが最初に実行される可能性があります。items

4

2 に答える 2

3

論理的な観点から、ConvertToDataTableバインディングはテーブル自体にあるべきではなく、foreach?

また、バインディングまたはビュー モデルを介してテーブル レイアウトを制御するべきではありませんか? カスタム バインドは、ハードコードされた値にとって非常に不適切な場所です。

とにかく、controlsDescendantBindingsあなたの友達ですか(docs):

カスタムバインディング:

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 });
    }
};

モデルを見る:

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

テンプレート:

<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/

免責事項: jQuery DataTables がどのように機能するか正確にはわからないため、サンプルは aircode です。私が言いたいのは、必要に応じてバインドを手動で制御できるということです。

于 2013-10-28T17:20:24.420 に答える
1

これが私が使用するカスタムバインディングです!これは、バインディングで定義したいすべてのデータテーブルオプションをカバーしています...

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

于 2015-12-04T22:37:24.400 に答える