- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
场景:
在网页上,我有三个包含表格标签的 div。
有 3 个按钮,单击每个按钮都会在带有 table 标签的特定 div 上创建数据表的实例。
数据表从服务器端获取数据
所有数据返回并显示,分页、过滤工作正常。
因此,当创建所有三个实例时,仅在创建的最后一个实例上使用 fnSettings() 返回正确的对象,而其他两个实例返回 null
因此,使用 fnData() 等 api 方法会抛出错误:“TypeError: Cannot read property 'aoData' of null”,因为该数据表实例的设置对象在某种程度上为 null
代码说明
我创建了一个名为 datagrid 的类,并创建了该类的多个实例:
/**
* datagrid class contains methods and properties that will help in controllling and manipulating the multiple instances of the datagrid class
*
* This function is the constructor for the datagrid class
*
* @param {string} domContainerSelector DOM selector of the element containing the datagrid
* @param {Array} columns Definitions of the columns of the datagrid
* @param {string} ajaxSource The url that the jqgrid will use to request for data
* @param {Object} configurationParameters The configuration parameters that will be used by the jqGrid and this datagrid instance. Currently suppoted configuration parameters are: initialCacheSize, iDisplayLength, sScrollY, bPaginate, bFilter, sDom, bSort
* @param {Object} uiCallback Contains callback functions that are used when a server request is in progress and after the completion of the request. Mainly used for showing progress indicators.
* @returns {datagrid}
*/
function datagrid(domContainerSelector, columns, ajaxSource, configurationParameters, uiCallback)
{
this.domContainerSelector = domContainerSelector;
this.domTableSelector = this.domContainerSelector + " #grid";
this.domRowSelector = this.domTableSelector + " tbody tr";
this.domGridWrapperSelector = this.domContainerSelector + " .dataTables_wrapper";
this.columns = columns;
this.ajaxSource = ajaxSource;
this.configParams = configurationParameters;
this.uiCallback = uiCallback;
this.cache= {
start: 0,
end: 0,
initialSize:this.configParams.initialCacheSize == undefined ? 2 : this.configParams.initialCacheSize,
pageSize:this.configParams.iDisplayLength == undefined ? 10 : this.configParams.iDisplayLength,
loading:false,
jsondata: {},
reset: function(){
this.start=0;
this.end=0;
this.loading=false;
this.jsondata={};
}
};
/**
* This method returns the row selected by the user
*
* @return {Object} Row object containing columns as its properties
*/
this.getSelectedRow = function()
{
var allrows = this.dataTable.fnGetNodes();
for (i = 0; i < allrows.length; i++)
if ($(allrows[i]).hasClass('row_selected'))
return this.dataTable.fnGetData(allrows[i]);
};
this.getPostDataValue=function(postData, key){
for (var i=0;i<postData.length;i++)
{
if (postData[i].name == key)
{
return postData[i].value;
}
}
return null;
};
this.setPostDataValue=function(postData, key, value){
for (var i=0; i<postData.length;i++)
{
if (postData[i].name == key)
{
postData[i].value = value;
}
}
};
this.setPostDataFilterValues=function(postData){
for (i=0;i<this.columns.length;i++)
{
var key="sSearch_"+i;
this.setPostDataValue(postData,key,this.columns[i].sSearch===undefined?'':this.columns[i].sSearch);
}
};
this.filterColumnKeyupHandler = function(evt) {
var id=evt.target.id;
var index=id.charAt(id.length-1);
var oldvalue=this.columns[index].sSearch;
var value = evt.target.value == '' ? undefined : evt.target.value;
if (oldvalue!=value) this.cache.reset();//resetting the cache because the datagrid is in dirty state
this.columns[index].sSearch=value;
if (evt.keyCode == 13) this.dataTable.fnFilter();
};
/**
* This method acts as the general button handler when an operation is in progress
*/
this.busyStateButtonHandler=function()
{
ui.showmessage("Another operation is in progress. Please wait for the operation to complete");
};
/**
* This method sets the event handlers for the datagrid
*/
this.setEventHandlers = function() {
var self=this;
$(this.domGridWrapperSelector + " input[class='columnfilterinput']").off("keyup").on("keyup", function(evt) {self.filterColumnKeyupHandler(evt,self)});
$(this.domGridWrapperSelector + " .filterbar .searchbtn").off("click").on("click", function() {self.dataTable.fnFilter()});
};
/**
* This method sets the appropriate event handlers to indicate busy status
*/
this.setBusyStatusEventHandlers=function()
{
$(this.domGridWrapperSelector + " input[class='columnfilterinput']").off("keyup").on("keyup", this.busyStateButtonHandler);
$(this.domGridWrapperSelector + " .filterbar .searchbtn").off("click").on("click", this.busyStateButtonHandler);
};
/**
* This method enables column specific filtering
*
* This methods adds filtering capability to columns whose definitions indicate that they are searchable (bSearchable:true)
*/
this.enablecolumnfilter = function() {
var self = this;
var oTable = self.dataTable;
var oSettings = oTable.fnSettings();
var aoColumns = oSettings.aoColumns;
var nTHead = oSettings.nTHead;
var htmlTrTemplate = "<tr class='filterbar'>{content}</tr>";
var htmlTdTemplate = "<td>{content}</td>";
var htmlInputTemplate = "<input type='text' name='{name}' id='{id}' class='{class}' /><div class='searchbtn' id='{searchbtnid}'><div class='icon-filter'></div></div>";
var isAnyColumnFilterable = false;
var htmlTr = htmlTrTemplate;
var allHtmlTds = "";
for (i = 0; i < aoColumns.length; i++)
{
var column = aoColumns[i];
var htmlTd = htmlTdTemplate;
if (column.bSearchable == true)
{
isAnyColumnFilterable = true;
var htmlInput = htmlInputTemplate;
htmlInput = htmlInput.replace('{name}', column.mData);
htmlInput = htmlInput.replace('{id}', "sSearch_" + i);
htmlInput = htmlInput.replace('{class}', 'columnfilterinput');
htmlTd = htmlTd.replace('{content}', htmlInput);
}
else
htmlTd = htmlTd.replace('{content}', '');
allHtmlTds += htmlTd;
}
if (isAnyColumnFilterable)
{
htmlTr = htmlTr.replace('{content}', allHtmlTds);
nTHead.innerHTML += htmlTr;
$(this.domGridWrapperSelector + " .filterbar input[class='columnfilterinput']").each(function(){
$(this).width($(this).parent().width()-26);
});
}
};
/**
* This method enables single selection on the rows of the grid
*/
this.enableSelection = function()
{
$(this.domRowSelector).die("click").live("click", function() {
if ($(this).hasClass('row_selected')) {
$(this).removeClass('row_selected');
}
else {
$(this).siblings().removeClass('row_selected');
$(this).addClass('row_selected');
}
});
};
this.loadDataIntoCache=function(postData, sourceUrl, start, length){
if (!this.cache.loading)
{
var postData=$.extend(true, [], postData);
var start = start==undefined?this.cache.end:start;
var length = length==undefined?this.cache.pageSize:length;
var end = start + length;
this.setPostDataValue(postData, "iDisplayStart", start);
this.setPostDataValue(postData, "iDisplayLength", length);
var self=this;
this.cache.loading=true;
$.ajax({
type: "POST",
url: sourceUrl,
data: postData,
success:
function(json, textStatus, jqXHR)
{
json = JSON.parse(json);
var olddata=self.cache.jsondata.aaData;
if (olddata===undefined) self.cache.jsondata = $.extend(true, {}, json);
else olddata.push.apply(olddata,json.aaData);
self.cache.end=end;
},
error:
function(jqXHR, textStatus, errorThrown)
{
ui.showmessage(jqXHR.responseText);//remove this from here
},
complete:
function()
{
self.cache.loading=false;
}
});
}
};
this.loadDataFromCache=function(postData,sourceUrl){
var start=this.getPostDataValue(postData, "iDisplayStart");
var length=this.cache.pageSize;
var end=start+length;
var sEcho = this.getPostDataValue(postData,"sEcho");
if (this.cache.end>=end)
{
var jsondata=$.extend(true, {},this.cache.jsondata);
var data=jsondata.aaData;
jsondata.aaData=data.splice(start,length);
jsondata.sEcho = sEcho;
var totalRecords=jsondata.iTotalRecords;
if ((this.cache.end-end)<((this.cache.initialSize*this.cache.pageSize)/2) && (totalRecords==0 || this.cache.end<totalRecords) ) this.loadDataIntoCache(postData, sourceUrl);//prefetch data if needed
return jsondata;
}
else
{
this.loadDataIntoCache(postData,sourceUrl);
return null;
}
};
/**
* This method interfaces with the backend end controller
*
* This method is called when the grid initiates any operation that requires server side processing
*
* @param {String} sSource The source url that will be used for the xhr request
* @param {Array} aoData Contains the parameters sent by the dataTable that will be forwarded to the backend controller
* @param {Function} fnCallback The callback function of the dataTable that gets executed to finally render the grid with the data
*/
this.interfaceWithServer = function(sSource, aoData, fnCallback)
{
this.setPostDataFilterValues(aoData);
var self=this;
if (this.cache.end==0)
{
this.setPostDataValue(aoData, "iDisplayStart", this.cache.start);
if (this.dataTable!=undefined) this.dataTable.fnSettings()._iDisplayStart=0;
this.loadDataIntoCache(aoData, sSource, 0, (this.cache.initialSize*this.cache.pageSize));
}
var data=this.loadDataFromCache(aoData,sSource);
if (data!=null) fnCallback(data);
else
{
this.setBusyStatusEventHandlers();
this.uiCallback.inprogress();
self.cacheLoadingTimerId=setInterval(function(){
if (self.cache.loading==false)
{
clearInterval(self.cacheLoadingTimerId);
var data=self.loadDataFromCache(aoData,sSource);
fnCallback(data);
self.uiCallback.completed();
self.setEventHandlers();
}
},500);
}
};
/**
* This method destroys the datatable instance
*
* Remove all the contents from the parent div and reinserts a simple table tag on which a fresh datatable will be reinitialized
*/
this.destroy = function()
{
$(this.domRowSelector).die("click");
$(this.domGridWrapperSelector).remove();//remove only the datatable generated dynamic code
$(this.domContainerSelector).prepend("<table id='grid'></table>");
};
/**
* The dataTable property holds the instance of the jquery Datatable
*/
this.dataTable = $(this.domTableSelector).dataTable({
"bJQueryUI": true,
"sScrollY": this.configParams.sScrollY == undefined ? "320px" : this.configParams.sScrollY,
"bAutoWidth": true,
"bPaginate": this.configParams.bPaginate == undefined ? true : this.configParams.bPaginate,
"sPaginationType": "two_button",
"bLengthChange": false,
"bFilter": this.configParams.bFilter == undefined ? true : this.configParams.bFilter,
"sDom": this.configParams.sDom == undefined ? '<"H"lfr>t<"F"ip>' : this.configParams.sDom,
"bSort": this.configParams.bSort == undefined ? true : this.configParams.bSort,
"iDisplayLength": this.configParams.iDisplayLength == undefined ? 10 : this.configParams.iDisplayLength,
"bServerSide": true,
"sAjaxSource": this.ajaxSource,
"fnServerData": this.interfaceWithServer.bind(this),
"oLanguage": {
"sZeroRecords": "No Records Found",
"sInfo": "_START_ - _END_ of _TOTAL_",
"sInfoEmpty": "0 to 0 of 0"
},
"aoColumns": this.columns
});
this.init=function(){
this.enableSelection();
this.enablecolumnfilter();
this.setEventHandlers();
};
this.init();
};
现在在我的网页中创建 3 个实例:
switch (dialog)
{
case "cusgrp_dialog":
var columndefs = [
{
"sTitle": "XWBNCD",
"mData": "xwbncd",
"sWidth": "40%"
},
{
"sTitle": "XWKHTX",
"mData": "xwkhtx",
"sWidth": "60%"
}
];
var ajaxSource = "./entities/Cusgrp";
var configurationParameters = {
bFilter: null,
sDom: 't<"dataTable_controlbar"ip>'
};
this.customergroupDatagrid = new datagrid(domContainerSelector, columndefs, ajaxSource, configurationParameters, uiCallback);
break;
case "slmen_dialog":
var columndefs = [
{
"sTitle": "PERSON",
"mData": "person",
"sWidth": "40%"
},
{
"sTitle": "PNAME",
"mData": "pname",
"sWidth": "60%"
}
];
var ajaxSource = "./entities/Slmen";
var configurationParameters = {
bFilter: null,
sDom: 't<"dataTable_controlbar"ip>'
};
this.salesmanDatagrid = new datagrid(domContainerSelector, columndefs, ajaxSource, configurationParameters, uiCallback);
break;
case "dists_dialog":
var columndefs = [
{
"sTitle": "DSDCDE",
"mData": "dsdcde",
"sWidth": "40%"
},
{
"sTitle": "DNAME",
"mData": "dname",
"sWidth": "60%"
}
];
var ajaxSource = "./entities/Dists";
var configurationParameters = {
bFilter: null,
sDom: 't<"dataTable_controlbar"ip>'
};
this.distributorDatagrid = new datagrid(domContainerSelector, columndefs, ajaxSource, configurationParameters, uiCallback);
break;
}
创建所有三个实例后,只有最后一个实例具有 fnSettings() 对象定义,其余实例为 fnSettings 返回 null,从而调用使用 aoData(它是 fnSettings() 返回对象的成员)的其他 api 方法无法读取null的aoData属性的错误
控制台预览:
这 3 个实例存储在 customergroupDatagrid、salesmanDatagrid、distributorDatagrid 变量中
创建 customergroupDatagrid 实例时
customergroupDatagrid.dataTable.fnSettings();//返回对象
创建 salesmanDatagrid 实例时
salesmanDatagrid.dataTable.fnSettings();//返回对象
customergroupDatagrid.dataTable.fnSettings();//返回空
创建distributorDatagrid实例时
distributorDatagrid.dataTable.fnSettings();//返回对象
salesmanDatagrid.dataTable.fnSettings();//返回 null
customergroupDatagrid.dataTable.fnSettings();//返回空
最佳答案
我认为问题在于您的表都具有相同的 ID。请注意,正确的 HTML 需要唯一的 ID: http://www.w3.org/TR/html401/struct/global.html#h-7.5.2
id = name [CS]
This attribute assigns a name to an element. This name
must be unique in a document.
这里有两个 jsfiddles。
http://jsfiddle.net/QFrz9/
var dt1 = $('#div1 #grid').dataTable();
alert('dt1 settings: ' + dt1.fnSettings());
var dt2 = $('#div2 #grid').dataTable();
alert('dt1 settings: ' + dt1.fnSettings());
alert('dt2 settings: ' + dt2.fnSettings());
var dt1 = $('#div1 #grid1').dataTable();
alert('dt1 settings: ' + dt1.fnSettings());
var dt2 = $('#div2 #grid2').dataTable();
alert('dt1 settings: ' + dt1.fnSettings());
alert('dt2 settings: ' + dt2.fnSettings());
第一个重复您的代码,对两个表使用相同的 ID。创建第一个表后会显示警报; fnSettings 不为空。然后在创建下一个表后显示警报,突然表 1 的 fnSettings 为空。第二个 jsfiddle 使用唯一的 id,问题就消失了。
也许您的表 ID 可以是 div ID 和“网格”的组合,例如 div1grid、div2grid 等。然后您可以使用 domContainerSelector + 'grid' 而不是 ' #grid'。
关于javascript - 使用 jquery 数据表的多个实例时 aoData 为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16463646/
我有一个带有嵌套数据的 angular 数据表,我正在尝试在行点击函数上创建另一个数据表。父数据表的 rowCallBack 函数。 这是我的外部数据表 html; 这是我生成数据表的方
我有一个字母数字列,其中包含诸如“1、2、2”之类的字符串。 当我在搜索中输入“1, 2, 2”时,它似乎返回带有“1,”和“2,”的所有单元格。 我该怎么做才能使搜索仅返回“1、2、2”? 使用数据
我有一个获取其数据服务器端的表,使用自定义服务器端初始化参数,这些参数因生成的报告而异。表格生成后,用户可以打开一个弹出窗口,他们可以在其中添加多个附加过滤器以进行搜索。我需要能够使用与原始表相同的初
在 datatables我希望能够隐藏所有列,但似乎无法正确使用语法。 这来自下面的代码和上面的链接,创建了一个显示所有列的按钮。有没有办法写这个以便我可以隐藏所有列? {
我正在使用 DataTable 创建一个交互式表。我有 9 列,其中 5 列是值。我想根据它们的具体情况更改每个单元格的背景颜色。 我已经开始尝试首先更改整行颜色,因为这似乎是一项更容易的任务。但是我
我有一个简单的例子来说明我的问题。我正在使用数据表 1.9。当数据表位于另一个 html 表内时,水平滚动时列标题不会移动。当它不在 html 表中时它工作正常。我的示例实际上取自他们的水平滚动示例,
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
这是添加按钮以将数据导出到 csv、pdf、excel 的数据表示例...... fiddle here https://datatables.net/extensions/buttons/examp
是否有任何方法可以更改 angularjs 数据表中的按钮样式(colvis、copy、print、excel)。 vm.dtOptions = DTOptionsBuilder.newOptions
我试图弄清楚如何加入 2 个数据表并更新第一个但应用了过滤器。 DT DT2 b c 1: 1 10 2: 2 10 3: 3 10 4: 4 10 5: 5 10 6: 6 10 7: 7 10
我有一个数据表,其中包含许多包含值的列。我还有另一列,它定义了我需要选择哪些列的值。我很难找到一种方法来做到这一点。 这是一个简单的例子。 > d d value.1 value.2 name
我正在使用 data.table 包。我有一个数据表,表示用户在网站上的操作。假设每个用户都可以访问一个网站,并对其执行多项操作。我的原始数据表是 Action (每一行都是一个 Action ),我
我想知道每个变量在每个组中变化了多少次,然后将结果添加到所有组中。 我是这样找到的: mi[,lapply(.SD, function(x) sum(x != shift(x), na.rm=T)
有人可以向我解释一下如何向页眉或页脚添加按钮吗?Datatables 的开发者 Alan 说你必须离开网络服务器才能使用 Table Tools 来使用按钮。但我在独立计算机上离线运行 Datatab
我希望按 id 和按顺序(时间)计算不同的东西。 例如,与: dt = data.table( id=c(1,1,1,2,2,2,3,3,3), hour=c(1,5,5,6,7,8,23,23,23
我正在尝试在 JIRA 小工具中使用数据表,但在我的表准备就绪后,没有可用的分页按钮。我有一个表,我正在以最简单的方式使用数据表:$("#mytableid").dataTable(); 浏览页面元素
我有 responsive 表单中的数据表。 数据表生成 child rows在小型设备上。在这一行中,我有一些输入控件。这会导致两个问题。 第一个问题:**隐藏子行中的值不会进入表单数据。** 第二
我在使用 JQuery DataTable 捕获 keydown 事件时遇到问题。我的目标是允许用户使用箭头键导航表的行。因此,当用户按下箭头键时,我想捕获 keydown 事件并移动表的选定行(这是
是否有任何方法可以以编程方式更改显示的行数,而无需从下拉列表中手动选择? 我已经知道如何更改默认行数。当表首次加载时,我希望它加载所有行,然后“刷新”表以可能仅显示前 10 行。但我想以编程方式刷新表
我有一个数据表,我应该对其进行更改,例如我想更改内容的状态,但该内容位于表的第三页。当我更改它时,数据表会自行刷新到第一页。我想做的是保留选定的页码并在刷新后回调它。这可能吗? 顺便说一句,我正在使用
我是一名优秀的程序员,十分优秀!