Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/472.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用jquery datatable的多个实例时,aoData为null_Javascript_Jquery_Jquery Datatables - Fatal编程技术网

Javascript 使用jquery datatable的多个实例时,aoData为null

Javascript 使用jquery datatable的多个实例时,aoData为null,javascript,jquery,jquery-datatables,Javascript,Jquery,Jquery Datatables,场景: 在一个网页上,我有三个包含表标签的div 有3个按钮,单击每个按钮可以在特定的div上创建一个带有table标记的datatable实例 datatable从服务器端获取数据 所有返回和显示的数据、分页、筛选都可以正常工作 因此,在创建所有三个实例时,仅对最后创建的实例使用fnSettings()返回正确的对象,而其他两个实例返回null 因此,使用fnData()etc api方法会抛出一个错误:“TypeError:无法读取null的属性'aoData',因为该datatable实例

场景:

在一个网页上,我有三个包含表标签的div

有3个按钮,单击每个按钮可以在特定的div上创建一个带有table标记的datatable实例

datatable从服务器端获取数据

所有返回和显示的数据、分页、筛选都可以正常工作

因此,在创建所有三个实例时,仅对最后创建的实例使用fnSettings()返回正确的对象,而其他两个实例返回null

因此,使用fnData()etc api方法会抛出一个错误:“TypeError:无法读取null的属性'aoData',因为该datatable实例的设置对象以某种方式为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();
};
/**
*datagrid类包含有助于控制和操作datagrid类的多个实例的方法和属性
* 
*此函数是datagrid类的构造函数
* 
*@param{string}domContainerSelector包含datagrid的元素的DOM选择器
*@param{Array}columns数据网格列的定义
*@param{string}ajaxSource jqgrid将用于请求数据的url
*@param{Object}configurationParameters jqGrid和此datagrid实例将使用的配置参数。当前支持的配置参数有:initialCacheSize、iDisplayLength、sScrollY、bPaginate、bFilter、sDom、bSort
*@param{Object}uiCallback包含在服务器请求进行中和请求完成后使用的回调函数。主要用于显示进度指标。
*@returns{datagrid}
*/
函数datagrid(domContainerSelector、columns、ajaxSource、configurationParameters、uiCallback)
{
this.domContainerSelector=domContainerSelector;
this.domTableSelector=this.domContainerSelector+“网格”;
this.domRowSelector=this.domTableSelector+“tbody tr”;
this.domGridWrapperSelector=this.domContainerSelector+“.dataTables\u wrapper”;
this.columns=列;
this.ajaxSource=ajaxSource;
this.configParams=配置参数;
this.uiCallback=uiCallback;
此.cache={
起点:0,
完:0,,
initialSize:this.configParams.initialCacheSize==未定义?2:this.configParams.initialCacheSize,
pageSize:this.configParams.iDisplayLength==未定义?10:this.configParams.iDisplayLength,
加载:false,
jsondata:{},
重置:函数(){
这个.start=0;
这个.end=0;
这个。加载=假;
this.jsondata={};
}
};
/**
*此方法返回用户选择的行
* 
*@return{Object}包含列作为其属性的行对象
*/
this.getSelectedRow=函数()
{
var allrows=this.dataTable.fnGetNodes();
对于(i=0;i如果((this.cache.end)我认为问题在于您的表都具有相同的ID。请注意,正确的HTML需要唯一的ID:

这里有两个jsfiddle。

第一个表复制您的代码,对两个表使用相同的id。它在创建第一个表后显示一个警报;fnSettings不为null。然后在创建下一个表后显示一个警报,表1的fnSettings突然为null。第二个JSFIDLE使用唯一的id,问题消失


也许您的表id可以是div id和“grid”的组合,例如div1grid、div2grid等。然后您可以使用domContainerSelector+“grid”而不是“#grid”。

我认为问题在于您的表都具有相同的id。请注意,正确的HTML需要唯一的id:

这里有两个jsfiddle。

第一个表复制您的代码,对两个表使用相同的id。它在创建第一个表后显示一个警报;fnSettings不为null。然后在创建下一个表后显示一个警报,表1的fnSettings突然为null。第二个JSFIDLE使用唯一的id,问题消失


也许您的表id可以是div id和“grid”的组合,例如,div1grid、div2grid等。然后您将使用domContainerSelector+“grid”而不是“#grid”。

您可以模拟相同的吗?您可以模拟相同的吗?虽然我同意您的回答,但我很确定w3schools作为一种资源是不受欢迎的。是的,我似乎忽略了这一方面,用unqiue选择器初始化了每个数据表,但是还是那个“身份证”问题出现了。@JayRizzi-针对w3学校的观点。我将答案编辑为参考w3.org。奇怪的是,这对我有帮助。我在代码中的任何地方都没有使用id。我认为DataTables使用id作为选择器(如果可用)。我只是完全删除了id。虽然我同意你的答案,但我非常确定w3学校是不赞成的作为一个资源,我似乎忽略了这一点,用unqiue选择器初始化了每个数据表,但仍然是相同的“id”问题终于解决了。@JayRizzi-关于w3学校的观点。我已经编辑了参考w3.org的答案。这帮助了我,奇怪的是。我在代码中的任何地方都没有使用id。我认为DataTables使用了id a
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;
        }
id = name [CS]
This attribute assigns a name to an element. This name 
must be unique in a document.
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());