1

我在一个页面上有两个DataTables对象,我们称它们为 searchResultsTable 和 currentPortfolioTable。当我单击按钮时,我正在使用fnReloadAjax插件按需重新加载 DataTables。但是,只有一个表加载了新数据 (currentPortfolioTable),searchResultsTable 确实执行了对数据的 ajax 请求,但无法将新的(有效的)数据加载到表中。

我尝试破坏 DataTable 并创建一个新的,甚至重写 fnReloadAjax 插件的部分内容,看看是否可以产生不同的结果。

即使只为 currentPortfolioTable 调用 fnReloadAjax,它也拒绝显示加载的新数据。

使用 DataTable 的 aoColumns 属性的 bVisible 状态显示/隐藏列时,也会出现 searchResultsTable 无法加载新数据的问题。

示例代码:

var dataTableObjects = dataTableObjects || {
    "searchResultsTable": {},
    "currentPortfolioTable": {}
};

var _rankingsRootUrl = window.ROOT + 'rankings/';

var _defaultDataTableSettings = {
    "aoColumns": [
        {   "bSortable": false,
            "sTitle": "Add to Portfolio",
            "bVisible": true
        },
        {
            "bSortable": true,
            "sTitle": "Name of Investment",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "Chart",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "Rating",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "Minimum",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "ROR",
            "bVisible": false
        },
        {   "bSortable": true,
            "sTitle": "Max DD",
            "bVisible": false
        },
        {   "bSortable": true,
            "sTitle": "Sharpe",
            "bVisible": false
        },
        {   "bSortable": true,
            "sTitle": "Sterling",
            "bVisible": false
        }
    ],
    "aaSorting": [
    ],
    "sAjaxSource": _rankingsRootUrl + 'search_results/',
    "bServerSide": true,
    "bProcessing": true,
    "bPaginate": false,
    "bLengthChange": false,
    "sScrollY": 200,
    "sScrollX": "100%",
    "sScrollXInner": "100%",
    "bScrollCollapse": true,
    "fnServerData": function ( sSource, aoData, fnCallback ) {
        $.ajax( {
            "dataType": 'json',
            "type": "POST",
            "url": sSource,
            "data": aoData,
            "success": fnCallback
        } );
    },
    "fnServerParams": function ( aoData ) {
        aoData.push(
            {"name": "program_type", "value": $(':input#RankingProgramType').val()},
            {"name": "program_name", "value": $(':input#RankingProgramName').val()},
            {"name": "min_investment", "value": $(':input#RankingMinimumInvestment').val()},
            {"name": "rate_of_return", "value": $(':input#RankingRateOfReturn').val()},
            {"name": "max_dd", "value": $(':input#RankingMaxDd').val()},
            {"name": "time_span", "value": $(':input#RankingTimeSpan').val()},
            {"name": "flags", "value": $(':input#RankingFlags').val()},
            {"name": "strategies", "value": $(':input#RankingStrategies').val()},
            {"name": "recommended", "value": $(':input#RankingRecommended').val()},
            {"name": "portfolio_id", "value": (window.PORTFOLIO && window.PORTFOLIO.id) || ""}
        );
    }
};

var _defaultCurrentPortfolioTableSettings = {
    "aoColumns": [
        {
            "bSortable": true,
            "sTitle": "Name of Investment",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "Chart",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "Rating",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "Minimum",
            "bVisible": true
        },
        {   "bSortable": true,
            "sTitle": "ROR",
            "bVisible": false
        },
        {   "bSortable": true,
            "sTitle": "Max DD",
            "bVisible": false
        },
        {   "bSortable": true,
            "sTitle": "Sharpe",
            "bVisible": false
        },
        {   "bSortable": true,
            "sTitle": "Sterling",
            "bVisible": false
        }
    ],
    "aaSorting": [
    ],
    "sAjaxSource": _rankingsRootUrl + 'current_portfolio/',
    "bServerSide": true,
    "bProcessing": true,
    "bPaginate": false,
    "bLengthChange": false,
    "sScrollY": 200,
    "sScrollX": "100%",
    "sScrollXInner": "100%",
    "bScrollCollapse": true,
    "fnServerData": function ( sSource, aoData, fnCallback ) {
        $.ajax( {
            "dataType": 'json',
            "type": "POST",
            "url": sSource,
            "data": aoData,
            "success": fnCallback
        } );
    },
    "fnServerParams": function ( aoData ) {
        aoData.push(
            {"name": "portfolio_id", "value": (window.PORTFOLIO && window.PORTFOLIO.id) || ""}
        );
    }
};

dataTableObjects.searchResultsTable = $('#search-results table').dataTable(_defaultDataTableSettings);
dataTableObjects.currentPortfolioTable = $('#currently-in-portfolio table').dataTable(_defaultCurrentPortfolioTableSettings);

$("#rankings").on("click", "a.add", function (e){
   dataTableObjects.searchResultsTable.fnReloadAjax('/datable1-url');
   dataTableObjects.currentPortfolioTable.fnReloadAjax('/datable2-url');
   e.preventDefault();
});

尝试修复:

  • 使用 fnReloadAjax 的回调方法来触发 dataTable2 的数据重新加载
  • 验证每个表的 id 是否唯一
  • 验证 dataTableJSObjects 是页面的正确且唯一的表
  • 控制台没有记录错误或问题
  • JShinted js 确保没有js错误或错误
  • 关闭 fnReloadAjax dataTableObjects.searchResultsTable 和 dataTableObjects.currentPortfolioTable 仍然无法正确重新加载
  • 使用 fnReloadAjax 替换为 fnDraw
4

4 回答 4

4

感谢您发布额外的源代码详细信息。我想我可能已经找到了问题...

fnReloadAjax插件的描述中,Allan Jardine添加了以下注释:

注意:要在使用服务器端处理时重新加载数据,只需使用内置 API 函数fnDraw而不是此插件。

现在,虽然我意识到您已经确认所请求的数据是正确的,并且第一个数据表在使用时甚至可以正确重新/datable1-url加载;但是,根据艾伦的说明,并且由于问题的神秘性质而缺乏更好的答案,我想说,您当前实施的问题很可能确实是由于不是适合该方式的解决方案你有你的表配置。/datable2-urlfnReloadAjaxfnReloadAjax

不过,我也意识到,fnReloadAjax由于现在已设置表格,因此仅更改为 fnDraw 并不能解决您的问题……是时候变得棘手了……

这是我的解决方案:

首先将这两行添加到脚本的顶部:

var isInitialLoadTable1 = true;
var isInitialLoadTable2 = true;

接下来,在每个 dataTable 设置变量中,在回调之后添加以下附加fnServerParams回调:

"fnInitComplete": function( oSettings, json ) {
    isInitialLoadTable1 = false;
}

确保在第二个表中更改isInitialLoadTable1initialLoadTable2[并且不要忘记结束大括号后的逗号fnServerParams:-)]

现在对于技巧......在fnServerData回调中更改调用的url设置,$.ajax如下所示:

"url": (isInitialLoadTable1 ? sSource : '/datable1-url'),

同样,请确保在此语句中为第二个 dataTable将两个1 更改为 2

最后,将您的点击事件更改为以下内容:

$("#rankings").on("click", "a.add", function (e) {
    dataTableObjects.searchResultsTable.fnDraw();
    dataTableObjects.currentPortfolioTable.fnDraw();
    e.preventDefault();
});

现在,我还没有对此进行测试,但真正的测试在于您的代码和数据。

希望这可以解决问题。

于 2012-04-29T16:59:34.743 回答
2

一种想法是,在两个不同的表上连续调用 fnReloadAjax 可能会导致 dataTable2 发生冲突,如果它等待 dataTable 1 完成加载,则不会遇到这种冲突。

fnReloadAjax 函数接受一个可能有帮助的回调参数...

例如:

dataTableObjects.dataTable1 = $('#search-results table').dataTable();
dataTableObjects.dataTable2 = $('#currently-in-portfolio table').dataTable();

$("#rankings").on("click", "a.add", function (e){
    dataTableObjects.dataTable1.fnReloadAjax('/datable1-url', null, reloadDataTable2, false);
    e.preventDefault();
});

// outside of the "ready" block
var reloadDataTable2 = function () {
    dataTableObjects.dataTable2.fnReloadAjax('/datable2-url');
};

我还没有测试过这个,所以我不确定它是否会起作用。

但是,我在寻找自己的问题的解决方案时看到了这个问题,我想我会提出这个想法。希望这可以帮助。

于 2012-04-25T20:06:17.613 回答
1

针对这个特定问题的解决方案是,为 dataTableObjects.currentPortfolioTable 返回的数据包含 DataTable 用于数据分页的值 sEcho,即这是哪一页数据。可以在DataTables with Server Side Data 的示例用法中看到 sEcho 。

dataTableObjects.currentPortfolioTable 的 sEcho 值始终设置为1,这显然导致 DataTables 始终认为数据仍然是原始数据集而不是新数据。将 sEcho 递增到在 AJAX 请求中传回的新数据的值修复了该问题。

于 2012-04-30T20:59:30.667 回答
1

我刚刚将一个示例放在一起,表明它应该可以正常工作:http: //live.datatables.net/aqazek/edit#javascript,html。我对 fnReloadAjax 进行了微小的调整,因此您可以看到重新加载对我的静态数据源的影响(只需用计数器重写其中一个单元格),但除此之外 - DataTables 站点没有任何更改。

因此,我认为要提供任何进一步的帮助,我们需要看到它不起作用的示例。

于 2012-04-29T07:44:14.827 回答