【问题标题】:free-jqGrid External Filtering Used With Grid's beforeRequest() or onPaging() Event用于 Grid 的 beforeRequest() 或 onPaging() 事件的 free-jqGrid 外部过滤
【发布时间】:2018-08-23 23:26:09
【问题描述】:

使用 jqGrid 免费版(4.15.6 版)显示有关发票的非常基本的信息(即:创建日期、到期日期、客户、总计、状态)。发票网格只显示了几个相关的列,因为它不需要显示更多。实际上,还有许多其他与发票相关的字段未显示。我想为最终用户提供基于许多其他参数过滤网格的能力,这些参数根本不属于网格内容的一部分。

我知道 jqGrid 提供内置搜索,您可以轻松地添加包含所有数据的隐藏列,但我觉得这对我们不利 - 发票包含大量数据 - 不一定存在的数据仅在发票数据库表中。我们希望网格在基本发票数据之外提供许多其他过滤选项,但我们不想使用内置过滤选项。相反,我想使用带有一堆搜索字段的单独 HTML 表,我们的服务器端代码会知道如何拉回这些字段)。当决定调用外部过滤器时,我们希望网格加载与该组合过滤器匹配的所有发票。如果选择使用网格的分页按钮进行导航,我们希望网格继续使用原始的外部过滤参数。

希望这是有道理的。也许我只是想多了,但我相当肯定网格的设计目的是使用它内置在过滤/搜索工具/对话框中,而且我还没有找到覆盖这种行为的方法。实际上,我使用的是较旧的 jqGrid,但涉及使用 jQuery 以自定义 HTML 和事件处理完全替换默认寻呼机。我永远无法用旧的 jqGrid 解决这个问题,所以我选择自己编写。但是该代码不是最佳的,即使我知道它也会受到很多批评。升级到 4.15.6 后,我想以最好的方式做到这一点,并且我想保持它的逻辑性和实用性。

我尝试使用 beforeRequest() 和 onPaging() 事件来更改“url”参数,认为如果我修改了 url,我可以更改 GET 以包含我们所有的自定义过滤字段。似乎这不起作用,因为 url 永远不会从最初定义的值改变。控制台日志记录确实显示事件触发但 url 没有更改。最重要的是,网格总是将自己的页面字段、_search 字段等传递给服务器,因此服务器永远不会看到过滤器请求。

如何定义自己的自定义过滤以及分页加载器,同时仍然利用内置分页事件?我错过了什么?

**** 删除了添加到与原始问题问题无关的问题的代码 *********

【问题讨论】:

  • 在 Guriddo jqGrid 中,searchGrid 方法中有一个未记录的参数 columns。此参数在定义时覆盖 colModel 允许定义您自己的搜索对话框表并保持同步分页和其他操作。我无法告诉你它是否也可以在 free-jqGrid 中使用。

标签: forms jqgrid external custom-events


【解决方案1】:

很难回答您的问题,因为您没有发布代码片段,显示您如何使用 jqGrid,并且因为不知道所有页面中可能需要显示的数据总数。

一般来说,实现自定义过滤有两种主要的替代方案:

  • 服务器端过滤
  • 客户端过滤

您还可以使用两种过滤的混合。例如,可以从服务器加载基于某些固定过滤器的所有发票(特定用户的所有发票或一个组织的所有发票,上个月的所有发票),然后使用loadonce: true, forceClientSorting: true选项对返回的进行排序和过滤客户端的数据。用户还可以使用搜索对话框的过滤工具栏在本地过滤数据子集。

客户端的性能在去年得到了本质的提升,从服务器加载相对较大的 JSON 数据可以非常快速地完成。因此,严格建议使用客户端过滤。为了更好地了解本地排序、过滤和分页的性能,我建议您尝试the demo 上的功能。您将看到对具有 5000 行和 13 列的网格进行本地过滤的时机更好,因为您可以预期主要来自到服务器的往返行程和在一些组织良好的数据库上处理服务器端过滤。这就是为什么我建议尽可能考虑使用客户端排序(或loadonce: true, forceClientSorting: true 选项)的原因。

如果您需要在服务器上过滤数据,那么您只需在每次请求时向服务器发送额外的参数。可以通过在postData 中包含其他参数来做到这一点。有关更多详细信息,请参阅the old answer。或者,可以使用serializeGridData 来扩展/修改数据,这些数据将设置到服务器。

数据从服务器加载后,可以在本地进行排序和过滤第一页数据将显示在网格中之前。要强制进行本地过滤,只需将forceClientSorting: true 额外添加到众所周知的loadonce: true 参数中。它强制对从服务器返回的数据应用 local 逻辑。因此可以使用postData.filterssearch: true 来强制进行额外的本地过滤,并使用sortnamesortorder 参数来强制进行本地排序。

关于使用隐藏列的另一个重要说明。每个隐藏列都会强制创建 DOM 元素,这些元素代表不需要的 <td> 元素。您在页面上放置的 DOM 元素越多,页面的速度就越慢。如果将使用本地数据(或者如果使用loadonce: true),则 jqGrid 将与每一行关联的数据保存两次:一次作为 JavaScript 对象,一次作为网格中的单元格(<td> 元素)。免费 jqGrid 允许使用“附加属性”而不是隐藏列。在这种情况下,不会将数据放置在网格的 DOM 中,但数据将保存在 JavaScript 对象中,并且能够以与其他列相同的方式通过其他属性进行排序或过滤。以最简单的方式可以删除所有隐藏列并添加additionalProperties 参数,该参数应该是带有附加属性名称的字符串数组。 additionalProperties 的元素可以是与 colModel 相同结构的对象,而不是字符串。例如,additionalProperties: [{ name: "taskId", sorttype: "integer"}, "isFinal"]。以the demo 为例。网格的输入数据可见hereAnother demo 显示搜索对话框包含除 jqGrid 列之外的其他属性。 searching 的注释部分 columns 显示了更高级的方法来指定列表和列的顺序以及在搜索对话框中显示的其他属性。

【讨论】:

  • 我已经能够结合您发布到类似问题的 cmets 的其他几个演示。我的 v4.15.6 可以很好地使用自定义外部过滤表单,并保持内置分页功能完好。但是,由于发票可以包含如此多的数据,最好让服务器提供构成主要网格内容的核心,然后按照您的建议使用客户端快速过滤可见列。但是,我想根据以下两件事之一来控制网格负载:1)状态或客户端在第一页加载时作为 url 参数传递给 PHP 脚本,或者....
  • 2) 所有外部可过滤选项都通过 postData 传递,并且在标准分页上重新加载网格。因此,如果由于正常分页而加载网格,则应用现有的 postData 过滤器(如果有)。但是,如果在初始页面加载时加载网格,我希望网格仅加载处于“未付费”状态的发票并可能分配给特定客户端,并且在分页时,网格应将这两个参数保留为过滤器。您能否提供一个示例,说明如何在初始页面加载时设置 jqGrid 过滤?
  • @Chance:我不确定我是否理解你的意思。一般来说,如果你想使用纯服务器端过滤,那么你必须自己实现所有必需的逻辑。例如,您可以使用一些postData 进行初始加载,然后对其进行修改。您可以使用var p = $("#gridid").jqGrid("getGridParam") 获取jqGrid 的所有 参数,您可以随时更改/替换p.postData,只需添加或删除p.postData 对象的某些属性/方法。此外,您可以使用localStorage 保存/恢复一些初始过滤器,以便下次访问同一页面。
  • @Chance:参见herehere 使用示例localStorage 和jqGrid。
  • 我在服务器上定义了过滤器,它运行良好。我了解您在初始加载后更改 postData 的意思。但是我仍然不能做的是让网格以我知道网格第一次调用服务器的方式将数据呈现给服务器。我已经尝试了一切,从在浏览器中添加参数到物理地址栏,在 url 中传递默认参数或在 jqGrid 选项中传递 postData 以定义默认选项。我不能强制网格在第一页加载时进行过滤。我不想使用 localStorage——我只想定义默认过滤.....
【解决方案2】:

请原谅我这样回答,但这个问题始于一个与过滤和分页相关但使用外部过滤源的主题。 Oleg 实际上有多个线程的演示,我可以使用它们来完成自定义过滤和维护默认的内置分页。所以他的答案将是原始问题主题的公认答案。

但是在原来的解决方案中,我遇到了另一个加载网格的问题。如果没有其他过滤器已经到位,我希望使用默认过滤值加载网格。那真的应该是一个不同的问题,因为它确实不影响第一个问题。

我发现另一个 Oleg 回复了一个完全不同的问题:

jqGrid - how to set grid to NOT load any data initially?

Oleg 回答了这个问题,这个答案解决了我们第二个需要加载一种方式,然后允许另一种方式。

因此,在初始加载时,我们会在服务器端查找过滤器参数。没有给出?我们使用默认过滤提取记录。参数在场?我们使用初始提供的参数。与初始加载的区别是我们没有 AJAX 退出。我们改为 json_encode 数据并将其放置在网格定义中,如下所示:

$('#grd_invoices').jqGrid(
...
url: '{$modulelink}&sm=130',
data: {$json_encoded_griddata},
datatype: 'local',
...
});

由于数据类型设置为“本地”,网格最初不会转到服务器,因此网格使用数据参数。一旦我们准备好过滤,我们使用 Oleg 的解决方案从另一个问题的另一个答案中动态应用过滤器,如下所示:

var myfilter = { groupOp: 'AND', rules: []};
myfilter.rules.push({field:'fuserid',op:'eq',data:$('#fuserid').val()});
myfilter.rules.push({field:'finvoicenum',op:'eq',data:$('#finvoicenum').val()});
myfilter.rules.push({field:'fdatefield',op:'eq',data:$('#fdatefield').val()});
myfilter.rules.push({field:'fsdate',op:'eq',data:$('#fsdate').val()});
myfilter.rules.push({field:'fedate',op:'eq',data:$('#fedate').val()});
myfilter.rules.push({field:'fwithin',op:'eq',data:$('#fwithin').val()});
myfilter.rules.push({field:'fnotes',op:'eq',data:$('#fnotes').val()});
myfilter.rules.push({field:'fdescription',op:'eq',data:$('#fdescription').val()});
myfilter.rules.push({field:'fpaymentmethod',op:'eq',data:$('#fpaymentmethod').val()});
myfilter.rules.push({field:'fstatus',op:'eq',data:$('#fstatus').val()});
myfilter.rules.push({field:'ftotalfrom',op:'eq',data:$('#ftotalfrom').val()});
myfilter.rules.push({field:'ftotal',op:'eq',data:$('#ftotal').val()});
myfilter.rules.push({field:'fmake',op:'eq',data:$('#fmake').val()});
myfilter.rules.push({field:'fmodel',op:'eq',data:$('#fmodel').val()});
myfilter.rules.push({field:'fserial',op:'eq',data:$('#fserial').val()});
myfilter.rules.push({field:'fitemid',op:'eq',data:$('#fitemid').val()});
myfilter.rules.push({field:'ftaxid',op:'eq',data:$('#ftaxid').val()});
myfilter.rules.push({field:'fsalesrepid',op:'eq',data:$('#fsalesrepid').val()});

var grid = $('#grd_invoices');
grid[0].p.search = myfilter.rules.length>0;
$.extend(grid[0].p.postData,{filters:JSON.stringify(myfilter)});
$('#grd_invoices').jqGrid('setGridParam',{datatype:'json'}).trigger('reloadGrid',[{page:1}]);

这允许我们让网格显示本地加载的初始数据,然后随后的过滤将网格数据类型更改为“json”,这会强制网格使用新的过滤器参数进入服务器,在那里它会加载更具体的过滤。

这要归功于 Oleg,因为我使用了他许多问题中的许多帖子来得出最终结果。谢谢@Oleg!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 2016-08-29
    • 1970-01-01
    相关资源
    最近更新 更多