【问题标题】:DataTables: How to set page in preInit?DataTables:如何在 preInit 中设置页面?
【发布时间】:2016-12-11 06:00:52
【问题描述】:

The docs 说我应该可以通过DataTablesApiInstance.page(pageNumber) 设置页面,但我无法让它工作。

所有其他 API 方法,如 searchorder 似乎都可以正常工作。

这是我的代码:

$(document)
    .on('preInit.dt', (ev, settings) => {
        let tableId = ev.target.id;
        let tableState = _.get(['datatables', tableId], history.state) || {};

        let api = new $.fn.dataTable.Api(settings);

        if(tableState.hasOwnProperty('page')) {
            api.page(tableState.page); // <-- problem is here; page doesn't get set
        }

        if(tableState.hasOwnProperty('search')) {
            api.search(tableState.search);
        }

        if(tableState.hasOwnProperty('order')) {
            api.order(tableState.order);
        }

        const setState = (key, value) => {
            history.replaceState(_.set(['datatables', tableId, key], value, history.state), '');
        };

        api.on('page', ev => {
            let info = api.page.info();
            // console.log('page', tableId, info.page);
            setState('page', info.page);
        });

        api.on('order', ev => {
            let order = api.order();
            // console.log('order', tableId, order);
            setState('order', order);
        });

        api.on('search', ev => {
            setState('search', api.search());
        });
    });

方法被命中,但页面未设置。我是否使用了错误的 API 方法?有没有其他方法可以在数据加载之前设置页面?

我正在使用datatables.net@1.10.12


如果我将调用推迟到init 而不是preInit,则会突出显示正确的页码,但数据仍来自第一页。如果我在此之上添加 0ms 延迟(如下所示),它确实有效,但会导致第二次数据获取 + 绘制。

if(tableState.page) {
    api.on('init', ev => {
        setTimeout(() => {
            api.page(tableState.page).draw('page');
        }, 0);

    });
}

如何在不产生第二个 ajax 请求的情况下设置页面?

【问题讨论】:

标签: datatables


【解决方案1】:

您可以使用displayStart 选项来定义当使用带有分页的DataTables 作为jQuery DataTables 的recommended by the author 时数据显示的起点。

它在服务器端处理模式下与表正常工作,只执行1个Ajax请求。

var table = $("#example").DataTable({
     "processing": true,
     "serverSide": true,
     "ajax": "/test",
     "displayStart": 200     
 });

来自documentation

注意这个参数是记录数(从0开始计数),而不是页码,所以如果你每页有10记录,想从第三页开始,应该是@987654333 @ 而不是 23

【讨论】:

  • 问题在于我不想将此代码复制到我在网站上使用的每个 DataTable 中。我正在尝试包罗万象,这就是为什么我在document 上监听preInit 事件。如果我可以从那里修改设置,我可以完成这项工作,但这是不可能的,不是吗?
  • @mpen,可能还有其他选择,但在我们深入探讨之前,为什么您不使用stateSave 来保存/恢复分页以及其他参数,例如搜索、顺序、等等。?如果你想实现自己的状态保存机制,可以使用stateSaveCallbackstateLoadCallback,不需要preInit.dt事件处理程序。
  • stateSave 是否仅适用于页面重新加载/返回?还是它永远记得它?因为我只希望在用户按下“返回”时恢复状态,这就是我开始走这条路的原因。
  • @mpen,有关该主题,请参阅 this post
  • 啊哈。这正是我想要做的。我以前没有看到,但我不能说我喜欢 Dex 的解决方案。将 JS 添加到页面的每个链接以清除状态是一个非常糟糕的 hack。我的解决方案似乎类似于Aliester's,除了我真的不想更改散列。我想我可以用状态保存+加载回调做我想做的事。我会试试的,谢谢!
【解决方案2】:

这并没有(直接)回答如何在 preInit 中设置页面的问题,但它解决了我的问题。

我们可以使用 stateLoadCallback 从历史 API 加载状态(包括页面),而不是像默认实现那样使用 localStorage(即使在导航离开然后再次返回时也会记住状态)。

$.extend(true, $.fn.dataTable.defaults, {
    stateSave: true,
    stateSaveCallback: (settings, data) => {
        let tableId = settings.nTable.id;
        if(!tableId) {
            // console.warn(`DataTable is missing an ID; cannot save its state`);
            return;
        }
        history.replaceState(_.set(['datatables', tableId], data, history.state), '');
    },
    stateLoadCallback: settings => {
        let tableId = settings.nTable.id;
        if(!tableId) {
            console.warn(`DataTable is missing an ID; cannot load its state`);
            return;
        }
        return _.get(['datatables', tableId], history.state) || null;
    }
});

【讨论】:

    猜你喜欢
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    相关资源
    最近更新 更多