【问题标题】:How do I override the default search functionality in JQGrid如何覆盖 JQGrid 中的默认搜索功能
【发布时间】:2014-04-29 14:09:31
【问题描述】:

我有一个 JQGrid 设置,搜索栏出现在顶部。对于文本字段,我希望搜索栏正常运行。在我创建带有一些完全匹配选项的下拉列表时也是如此。但是,对于日期字段或数字范围,我想创建一个允许用户按范围搜索的下拉列表。我假设在这些情况下,我需要覆盖 JQGrid 的现有搜索功能并编写自己的搜索功能。

我假设这是使用 fn 搜索选项完成的。到目前为止,我已经做到了以下几点。这将完全按照我的意愿创建网格和搜索选项。但是,尝试进行任何搜索都会清除整个网格,大概是因为它不知道如何处理特殊的日期和范围下拉菜单。我很感激有关如何继续的见解。如果 JQGrid 中已经存在此功能,请告诉我如何访问它?

顺便说一句,我想让所有处理都在本地进行。 JQGrid 之类的主要优点是消除了来自多个数据库请求的负载,并消除了由大量 HTTP 连接带来的延迟和开销。

<script>
    $("#grid1").jqGrid({
        datatype:       "local",
        height:         250,
        colNames:       ['CF Template', 'Error Date', 'Skey', 'Type', 'Summary'],
        colModel:       [

                                {   name: 'page_name',
                                    index: 'page_name',
                                    width: 400,
                                    sorttype: 'text',
                                    search:true,
                                    stype:'text'
                                }
                                , 
                                {   name: 'row_timestamp',
                                    index: 'row_timestamp',
                                    width: 100,
                                    sorttype: 'date',
                                    search:true,
                                    stype:'select',
                                    searchoptions: {
                                        value:{'0':'Any','2014-2-01_2014-2-28':'February','2014-3-01_2014-3-31':'March','2014-4-01_2014-4-30':'April'},
                                        dataEvents: [
                                            {
                                                type: 'change',
                                                fn: function(e) {
                                                    alert($('#gs_row_timestamp option:selected').val());
                                                    alert($('#gs_row_timestamp option:selected').text());
                                                    alert('4');
                                                }
                                            }
                                        ]
                                    }
                                }
                                , 
                                {   name: 'row_id',
                                    index: 'row_id',
                                    width: 100,
                                    sorttype: 'int',
                                    search:true,
                                    stype:'select',
                                    searchoptions: {
                                        value:{0:'Any',2:'0 - 12000000000',3:'12000000000 - 24000000000',4:'24000000000 - 36000000000',5:'36000000000 - 48000000000',6:'48000000000 - 60000000000'},
                                        dataEvents: [
                                            {
                                                type: 'change',
                                                fn: function(e) {
                                                    alert($('#gs_row_id option:selected').val());
                                                    alert($('#gs_row_id option:selected').text());
                                                    alert('2');
                                                }
                                            }
                                        ]
                                    }
                                }
                                , 
                                {   name: 'error_type',
                                    index: 'error_type',
                                    width: 100,
                                    sorttype: 'text',
                                    search:true,
                                    stype:'select',
                                    searchoptions: {
                                        value:{0:'Any',2:'Application',3:'Database',4:'Expression',5:'MissingInclude'},
                                        dataEvents: [
                                            {
                                                type: 'change',
                                                fn: function(e) {
                                                    alert($('#gs_error_type option:selected').val());
                                                    alert($('#gs_error_type option:selected').text());
                                                    alert('1');
                                                }
                                            }
                                        ]
                                    }
                                }
                                , 
                                {   name: 'error_summary',
                                    index: 'error_summary',
                                    width: 500,
                                    sorttype: 'text',
                                    search:true,
                                    stype:'text'
                                }

                        ],
        multiselect:    false,
        rowNum:         25,         // Number of rows shown per page; must also change down below
        pager:          '#pager1',  
        height:         250,        
        altRows:        true,                       // Allows for styling of alt rows
        altclass:       'altRowClass',              // Create striped rows
        viewrecords:    true,                       // Show recordcount in lower right corner
        ignoreCase:     true,                       // Case insensitive searches
        multiSort:      true,
    </script>

更新

似乎使用 e.stopImmediatePropagation() 可以防止网格清除,但我不确定如何从那里控制搜索。我应该查看定义搜索栏以设置一些特殊搜索功能的行而不是 fn?

    $("#grid1").jqGrid('filterToolbar', {stringResult: true, searchOnEnter: false, defaultSearch : "cn"});

更新

我想到一些示例数据可能会有所帮助。以下是页面上定义的一些记录。它们与 JQGrid 在同一页面上加载一次,然后所有搜索和过滤都应在本地进行。

        var mydata = [

                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\home.cfm"
                        , row_timestamp:    "2014-04-29 13:25:08.528"
                        , row_id:   "135200030"
                        , error_type:   "MissingInclude"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\home.cfm"
                        , row_timestamp:    "2014-04-29 13:24:48.575"
                        , row_id:   "135200040"
                        , error_type:   "MissingInclude"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Report\\repot_file_1.cfm"
                        , row_timestamp:    "2014-04-25 08:46:04.428"
                        , row_id:   "135200050"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Report\\repot_file_1.cfm"
                        , row_timestamp:    "2014-04-25 08:46:03.944"
                        , row_id:   "135200060"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Test\\jqtest.cfm"
                        , row_timestamp:    "2014-04-16 10:10:14.729"
                        , row_id:   "135200070"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Activity\\loader_file_1.cfm"
                        , row_timestamp:    "2014-04-15 16:47:51.477"
                        , row_id:   "135200080"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Blank\\loader_file_2.cfm"
                        , row_timestamp:    "2014-04-15 16:47:50.071"
                        , row_id:   "135200090"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Activity\\loader_file_1.cfm"
                        , row_timestamp:    "2014-04-15 16:42:22.18"
                        , row_id:   "135300000"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Blank\\loader_file_2.cfm"
                        , row_timestamp:    "2014-04-15 16:42:20.664"
                        , row_id:   "135300010"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 11:53:38.01"
                        , row_id:   "135300020"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 11:28:23.948"
                        , row_id:   "135300030"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 11:07:24.76"
                        , row_id:   "135300040"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 10:30:13.026"
                        , row_id:   "135300050"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\CustomTag\\stored_proc.cfm"
                        , row_timestamp:    "2014-04-08 09:03:21.588"
                        , row_id:   "135300060"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\EdiErrorQueue\\INVN\\Frameset_1.cfm"
                        , row_timestamp:    "2014-02-19 09:52:43.078"
                        , row_id:   "135300070"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\EdiErrorQueue\\INVN\\Frameset_1.cfm"
                        , row_timestamp:    "2014-02-19 09:46:10.906"
                        , row_id:   "135300080"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }

        ];
        for (var i = 0; i < mydata.length; i++)
            jQuery("#grid1").jqGrid('addRowData', i + 1, mydata[i]);
        jQuery("#grid1").setGridParam({ rowNum: 25 }).trigger("reloadGrid");

【问题讨论】:

  • 顺便说一句,“return false”和“e.preventDefault()”都不起作用。

标签: javascript jquery jqgrid


【解决方案1】:

问题

确实,jqGrid 不允许您定义自己的过滤函数以在过滤本地数据时应用。您想要实现的目标是可能的,但远非简单。原因之一是 jqGrid 依赖 jLinq 来执行搜索。但它并不是简单地调用 jLinq 来进行搜索,jLinq 的代码被复制粘贴到 jqGrid 代码中并在网格内部的中间调用......这使得无法以干净的方式扩展搜索功能。

这就是您在尝试提供自己的更改事件处理程序时遇到困难的原因。处理程序的默认代码是:

function(){
    triggerToolbar();
    return false;
}

triggerToolbar 函数是一个“无所不能”的函数,它将重新加载数据,重新绘制完整的网格将所有库机器,并在中间的某个地方过滤数据,无需任何钩子让您拦截搜索功能。

从这里,我可以看到三个解决方案:

  • 向 jqGrid 开发人员请求该功能
  • 修改jqGrid的代码。当我查看时,似乎很难做到这一点,同时确保你没有破坏图书馆。
  • 黑客方式:让jqGrid相信数据来自服务器,自己过滤

解决方案

我将仅扩展第三种解决方案。这个想法是利用 jqGrid 使用 jQuery 与服务器通信并在 jQuery 中注册 ajax 代理这一事实。这个代理会拦截所有的ajax调用,并根据jqGrid发送的查询参数返回你本地的数据。这将在过滤器更改时执行所有 jQuery 机制,但它可以工作。

1。创建代理

第一步是将您当前的设置转换为 jqGrid 认为数据来自服务器的设置。您可以使用函数$.ajaxTransport (documentation) 来执行此操作,您可以向该函数提供一个函数,该函数将在任何ajax 调用之前被调用。根据这些选项,您可以决定是要提供自己的对象来处理调用,还是让$.ajax() 完成其通常的工作。我基于一个已知的 url 做出这个决定,稍后我们将把它提供给 jqGrid。这可以是任何东西,只要它不是跨域的(如果它可能包含查询参数,请不要像我一样使用当前 URL)。代码如下:

var mydata = [ /* Your local data */ ];
var gridurl = window.location.href + "/mygrid";

$.ajaxTransport("json", function(options) {
  if(options.url.indexOf(gridurl) === 0) {
    return {
      send: function(headers, completeCallback) {
        setTimeout(function(){ //We still want the call to be asynchroneous
            completeCallback(200, "success", {json: mydata});
        }, 10);
      },
      abort: function() {
        //Do nothing
      }
    };
  }
});

以及更新的 jqGrid 设置:

$("#grid1").jqGrid({
    url:       gridurl,
    datatype:  "json",
    height:    250,
    colNames:  ['CF Template', 'Error Date', 'Skey', 'Type', 'Summary'],
    /* ... */
});

//No call to addRowData

2。实现过滤器

完成第 1 步后,您应该已经能够加载和显示网格了。现在让我们修改代理,使其根据 jqGrid 放在 url 中的搜索参数过滤数据。实际上,在处理远程数据时,jqGrid 完全依赖服务器来过滤数据。它只是将查询参数附加到 url,其中参数名称是列 id,参数值是表单元素的值。例如:?page_name=home&amp;row_timestamp=2014-2-01_2014-2-28 如果您在“CF 模板”的文本字段中输入了“home”,在“错误日期”的下拉列表中输入了“February”。

所以我们首先需要的是一种解析 URL 查询参数的方法。你可以使用 jQuery 插件,自己编写,或者ask StackOverlfow :)

function getParameterByName(url, name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(url);
    return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

然后是过滤数据的函数。设计将主要取决于您和您的要求(您可以想象使用 jLing 使这更容易,就像 jqGrid 所做的那样)。我使用了一个基本示例,我们希望根据范围过滤row_idrow_id 参数与 _ 拆分以解析范围的边界。请注意,在我的示例中,我只考虑row_id,但您必须为所有列编写过滤器,即使是之前由 jqGrid 处理的列(代理必须像服务器一样运行)。

//Filtering split in two functions: 
// -one to parse the url and identify what filters to apply
// -one to do the actual filtering

function getFilterOptions(url) {
    var filterOptions = {};
    var row_id = getParameterByName(url, "row_id"); 
    if (row_id && row_id != "*") { //"*" == Any
        filterOptions.row_id = row_id.split("_");
    }
    return filterOptions;
}

//Uses Array.filter(), may require a polyfill on older browsers
function filterData(data, filterOptions) {
    return data.filter(function(row) { 
        if (filterOptions.row_id) {
            return filterOptions.row_id[0] <= row.row_id 
                && row.row_id <= filterOptions.row_id[1]
        }
        return true;
    });
}

然后更新代理以使用过滤器。

$.ajaxTransport("json", function(options) {
  //options.url is the query sent by jqGrid, including search parameters
  if(options.url.indexOf(gridurl) === 0) {
    var filterOptions = getFilterOptions(options.url); 
    return {
      send: function(headers, completeCallback) {
        setTimeout(function(){
            //this is what jqGrid will receive.
            var filteredData = filterData(mydata, filterOptions);
            completeCallback(200, "success", {json: filteredData});
        }, 10);
      },
      abort: function() {
        //Do nothing
      }
    };
  }
});

最后,在 jqGrid 设置中激活搜索。我已将小丑值0 替换为*,并将其他格式为&lt;min&gt;_&lt;max&gt; 的值替换为getFilterOptions()

$("#grid1").jqGrid({
    url:       gridurl,
    datatype:  "json",
    height:    250,
    colNames:  ['CF Template', 'Error Date', 'Skey', 'Type', 'Summary'],
    colModel:  [{/* template column */},
               {/* date column */},
               {   
                name: 'row_id',
                index: 'row_id',
                width: 100,
                sorttype: 'int',
                search:true,
                stype:'select',
                searchoptions: {
                    value: {
                        '*':'Any', //Notice: joker used in getFilterOptions
                        '0_12000000000':'0 - 12000000000', 
                        '12000000000_24000000000':'12000000000 - 24000000000',
                        /* ... */
                    }
                    //no event handler
                }
               },
               /* ... */
               ],
    /* ... */
});

3。完成过滤器实现,尽情享受吧!

您还有一些工作要做,即设计和编写实际的过滤器,但是您有一个可行的解决方案来在 jqGrid 中进行自定义搜索。我使用您的测试数据在本地设置上对其进行了测试,没有遇到任何问题。如果我在将我的代码转换为这个答案时忘记了什么,请告诉我。

【讨论】:

  • 这是一个令人难以置信的答案,尽管我需要一些时间来整理我的想法。谢谢你。是否有可能进一步扩展自定义过滤器本身以及它们如何将数据传递回 JQGrid?代码块中的一些 cmets 会有很大帮助。 :)
  • 我认为这是简单的部分,无论如何你都会重新编写它,但添加了一些 cmets。也许你不知道Array.filter()? jqGrid 期望 ajax 响应是已经过滤的数据集。这就是我们给completeCallback 的最后一个参数(它通知“ajax”请求已完成)。我还对 jqGrid 如何请求服务器进行了一些扩展。希望这会有所帮助。
  • 很抱歉,我已经被其他项目拖走了,还没有机会尝试实现它。不过,这个概念似乎非常扎实,我感谢您为它所做的所有工作。当赏金即将到期时,我将标记为答案。谢谢。
  • 好的。有时间可以随时提出任何问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
相关资源
最近更新 更多