free-jqGrid与Grid的beforeRequest()或onPaging()事件一起使用的外部过滤

时间:2018-08-23 23:26:10

标签: forms jqgrid external custom-events

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

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

希望这是有道理的。也许我只是想得太过分了,但是我可以肯定网格是设计为使用它内置在过滤/搜索工具/对话框中的,并且我仍然没有发现可以覆盖此行为。实际上,我使用的是较旧的jqGrid,但涉及使用jQuery通过自定义HTML和事件处理完全替换默认的传呼机。我永远无法用较旧的jqGrid弄清楚这一点,所以我选择自己编写。但是该代码并不是最佳代码,即使我知道它也受到很多批评。升级到4.15.6后,我想以最佳方式做到这一点,并且希望保持逻辑性和实用性。

我尝试使用beforeRequest()和onPaging()事件来更改“ url”参数,以为如果修改了url,则可以更改GET以包括所有自定义过滤字段。由于url从未从原始定义的值更改,因此似乎不起作用。控制台日志记录确实显示了事件触发,但未更改url。最重要的是,网格始终将其自己的page字段,_search字段等传递给服务器,因此服务器从不看到过滤器请求。

如何定义自己的自定义过滤功能和分页加载程序,并仍然利用内置的分页事件?我想念什么?

****已添加到问题的代码,与原始问题无关*****

2 个答案:

答案 0 :(得分: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为例。可以看到here网格的输入数据。 Another demo显示搜索对话框除了jqGrid列之外还包含其他属性。 columns中带注释的部分searching显示了一种更高级的方法,用于指定列表以及列的顺序和在搜索对话框中显示的其他属性。

答案 1 :(得分:0)

请原谅我这样的回答,但是这个问题开始于与过滤和分页有关的一个主题,但是使用了外部过滤源。 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',
...
});

由于数据类型设置为'local',所以网格最初不会进入服务器,因此data参数由网格使用。一旦准备好进行过滤,就可以从另一个问题的另一个答案中使用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”,这迫使网格使用新的过滤器参数进入服务器,并在其中加载更具体的过滤。 / p>

信用归功于奥列格(Oleg),因为我利用他在许多问题上的许多帖子来得出最终结果。谢谢@Oleg!