【问题标题】:jqGrid: using multiple methods to filter datajqGrid:使用多种方法过滤数据
【发布时间】:2011-04-27 19:44:20
【问题描述】:

我的要求是显示一个包含多个过滤器的页面以应用于网格数据。

假设我们正在讨论订单,并且订单具有以下属性

public class Order {
    public int OrderID
    public DateTime OrderDate
    public DateTime ShipmentDate
    public int OrderTotal
    public int OrderStatus
}

在 jqgrid 对象中,我显示了所有属性除了 OrderStatus

要求是创建一个具有

  • 左侧的jqGrid
  • 右侧的面板

在右侧面板中,用户将看到代表每个可能的 OrderStatus 值的复选框列表,并且他希望使用这两种方法进行搜索(例如选择复选框“已发货订单”,然后使用大于某个值的金额过滤网格)

我已经在 jqGrid 对象中配置了高级过滤 (multiplesearch:true),并且我能够创建组合字段和逻辑运算符的复杂过滤器。

关于当用户按下搜索按钮时如何从右侧面板提交数据的任何想法?

更新 1

序言:Oleg 样品很棒,但不幸的是不符合我客户的要求 :(

@Oleg:我不明白你为什么这么认为:

如果数据在网格之外 您将看到订单详情 右窗格仅适用于选定行。 所以用户不会那么好 数据概览。

也许我的描述不是很清楚,但我不会显示任何订单细节。为了更好地阐明我的要求,我修改了您的示例,以向您展示所需的最终 UI,如下图所示:

客户希望使用两种方法或同时使用两种方法来过滤网格中的数据:

  • 使用网格本身提供的multiplesearch 工具(感谢提及解决方法)
  • 使用提供的自定义搜索面板(右侧带有复选框)

从功能的角度来看,需求很容易表达:当用户单击复选框或使用本机 multiplesearch 进行搜索时,我应该将值发布到服务器,包括复选框状态。

总结一下,我应该:

  • 当通过原生multiplesearch发帖时添加复选框状态
  • 当用户点击复选框时添加当前multiplesearch 状态(如果有)

有没有办法做到这一点?

【问题讨论】:

    标签: asp.net asp.net-mvc search jqgrid jqgrid-asp.net


    【解决方案1】:

    我非常了解这个要求。在关闭的情况下,我使用了 inside of jqGrid 复选框。将信息包含在 jqGrid 中的最大优势不仅在于易于搜索。如果数据在网格之外,您将在右侧窗格中显示订单详细信息仅适用于选定行。所以用户不会对数据有那么好的overview

    为了能够在表格中放置许多复选框而无需永久水平滚动,我使用Vertical text inside table headers using a JavaScript-based SVG library 中描述的技术旋转了具有“复选框的列的标题。这种旋转在 IE 中看起来并不完美,但在其他浏览器中它可以完美运行.

    您可以将来自OrderStatus 字段的数据保存在隐藏列中,并将位掩码解码为布尔值,从而在客户端或服务器端构建复选框。

    因为要使用multiplesearch:true,所以我不得不提一下jQuery.clone 的一个bug,它跟在所有版本的IE 浏览器中jqGrid multi-search 的bug 一样。如果您将多个搜索过滤器定义为一个,则只会使用第一个搜索过滤器,因为所有其他过滤器的操作字段将被读取为undefined。很可惜,但是刚刚发布的 jQuery 1.4.3 也没有修复这个 bug。为了能够使用multiplesearch:true,您可以使用Jiho Han on trirand.com forum 提出的解决方法建议。

    您可以在the demo example 中看到生成网格的所有内容

    您可以在其中搜索多个字段

    对应代码:

    var myData = [
        { orderID: "10", orderDate: "2010-09-18", shipmentDate: "2010-09-20", orderStatus: "2" },
        { orderID: "15", orderDate: "2010-09-20", shipmentDate: "2010-09-24", orderStatus: "3" },
        { orderID: "20", orderDate: "2010-10-16", shipmentDate: "2010-10-17", orderStatus: "1" }
    ];
    // decode 'orderStatus' column and add additional boolean data based on the bitmap mask
    for (var i=0, l=myData.length; i<l; i++) {
        var myRow = myData[i];
        var orderStatus = parseInt(myRow.orderStatus, 10);
        myRow.airPost = (orderStatus & 2) != 0? "1": "0";
        myRow.heavy = (orderStatus & 1) != 0? "1": "0";
    }
    var grid = jQuery('#list');
    grid.jqGrid({
        data: myData,
        datatype: 'local',
        caption: 'Order Details',
        height: 'auto',
        gridview: true,
        rownumbers: true,
        viewrecords: true,
        pager: '#pager',
        rownumbers: true,
        colNames: ['Order ID', 'Order', 'Shipment', 'Air-Post', 'Heavy', 'RowVersion'],
        colModel: [
            { name: 'orderID', index: 'orderID', key:true, width: 120, sorttype: 'int' },
            { name: 'orderDate', index: 'orderDate', width: 180,
              sorttype: 'date', formatter: 'date' },
            { name: 'shipmentDate', index: 'shipmentDate', width: 180,
              sorttype: 'date', formatter: 'date' },
            { name: 'airPost', width: 21, index: 'airPost', formatter: 'checkbox', align: 'center',
              editoptions: { value: "1:0" }, stype: 'select', searchoptions: { value: "1:Yes;0:No" } },
            { name: 'heavy', width: 21, index: 'heavy', formatter: 'checkbox', align: 'center',
              editoptions: { value: "1:0" }, stype: "select", searchoptions: { value: "1:Yes;0:No" } },
            { name: 'orderStatus', index: 'orderStatus', width: 50, hidden: true }
        ]
    }).jqGrid ('navGrid', '#pager', { edit: false, add: false, del: false, refresh: true, view: false },
                {},{},{},{multipleSearch:true})
      .jqGrid ('navButtonAdd', '#pager', { caption: "", buttonicon: "ui-icon-calculator", title: "choose columns",
          onClickButton: function() {
              grid.jqGrid('columnChooser');
          }
      });
    

    rotateCheckboxColumnHeaders 和高级搜索中的错误修复是这样定义的

    // we use workaround from http://www.trirand.com/blog/?page_id=393/bugs/in-multiple-search-second-and-subsequent-ops-are-sent-as-undefined-in-ie6/
    // to fix the bug in the jQuery.clone (see http://bugs.jquery.com/ticket/6793 and
    // dscussion on the http://api.jquery.com/clone/
    jQuery.event.special.click = {
        setup: function() {
            if (jQuery(this).hasClass("ui-search")) {
                jQuery(this).bind("click", jQuery.event.special.click.handler);
            }
            return false;
        },
        teardown: function() {
            jQuery(this).unbind("click", jQuery.event.special.click.handler);
            return false;
        },
        handler: function(event) {
            jQuery(".ui-searchFilter td.ops select").attr("name", "op");
        }
    };
    var rotateCheckboxColumnHeaders = function (grid, headerHeight) {
        // we use grid as context (if one have more as one table on tnhe page)
        var trHead = jQuery("thead:first tr", grid.hdiv);
        var cm = grid.getGridParam("colModel");
        jQuery("thead:first tr th").height(headerHeight);
        headerHeight = jQuery("thead:first tr th").height();
    
        for (var iCol = 0; iCol < cm.length; iCol++) {
            var cmi = cm[iCol];
            if (cmi.formatter === 'checkbox') {
                // we must set width of column header div BEFOR adding class "rotate" to
                // prevent text cutting based on the current column width
                var headDiv = jQuery("th:eq(" + iCol + ") div", trHead);
                headDiv.width(headerHeight).addClass("rotate");
                if (!jQuery.browser.msie) {
                    if (jQuery.browser.mozilla) {
                        headDiv.css("left", (cmi.width - headerHeight) / 2 + 3).css("bottom", 7);
                    }
                    else {
                        headDiv.css("left", (cmi.width - headerHeight) / 2);
                    }
                }
                else {
                    var ieVer = jQuery.browser.version.substr(0, 3);
                    // Internet Explorer
                    if (ieVer !== "6.0" && ieVer !== "7.0") {
                        jQuery("span", headDiv).css("left", 0);
                        headDiv.css("left", cmi.width / 2 - 4).css("bottom", headerHeight / 2);
                    }
                    else {
                        headDiv.css("left", 3);
                    }
                    headDiv.parent().css("zoom",1);
                }
            }
        }
    };
    

    如果您更喜欢将复选框保留在网格之外,您可以在 onSelectRow 事件处理程序中解码位掩码 OrderStatus

    更新:我一开始确实误解了您的要求。看看modified example。现在看起来像

    它更接近你的需要。

    【讨论】:

    • 哇!很棒的样品。感谢您花时间整理东西。无论如何,这不符合我的要求,而且我认为我没有最好地解释它。请查看我的帖子编辑以获取更多详细信息。谢谢!
    • @Lorenzo:我不确定您是否看过我的 "UDPATED" 部分,该部分是我在您取消问题后写的。这是否更接近于解决您的问题?
    • 太棒了!我今天才有时间看到你的更新。这正是我一直在寻找的。不能给+5,但可以肯定:谢谢! :)
    • @Lorenzo:我很高兴听到这个消息。我认为这个例子也可以帮助其他人。
    • 我找到了另一种以更快的方式做同样事情的方法。您能否在其他答案中查看它,如果使用它有任何缺点,请给我一些建议?谢谢!
    【解决方案2】:

    作为跟进,我在这里包括另一种我发现获得相同结果的方法。

    此方法假设使用jqGrid的postData参数。在该方法中,我定义了各种函数来验证复选框的当前状态,并将参数发送到可用于过滤的服务器。

    这是一个示例

    postData: {
        pending: function () {
            if ($("#cb_pending").is(':checked')) {
                return true;
            } else {
                return false;
            }
        }
    }
    

    这种解决方案相对于 Oleg 所描述的解决方案的优势在于,可以在服务器端使用混合逻辑运算符 (AND/OR),而使用 Oleg answer 中的过滤器部分是不可能的。

    编码愉快!

    【讨论】:

    • 向你提出同样的建议是我的第一个想法。我建议很多人这样做(参见stackoverflow.com/questions/2928371/…),但我很快发现了一些问题。 1)你没有写你使用哪种数据类型('json','local',...) 2)不知道你是否使用loadonce:frue,所以客户端搜索。 3) 最重要的是,多重(高级)搜索的过滤器与外部过滤器的复选框之间可能存在冲突。我应该更详细地解释这个问题:
    • 因为您的要求之一是使用multiplesearch 设施,您必须保存有关布尔状态的信息(如“待定”)jqGrid 内部。您当然可以修改 afterShowSearch 内的多搜索对话框(例如,请参阅来自 stackoverflow.com/questions/3981874/… 的 Justin Ethier 的建议。我觉得方法有点复杂,但它会起作用。我看到的最大问题 冲突 在过滤器之间。例如,我们有一个隐藏列“待定”,并使用高级搜索来设置“fasle”
    • 然后我们检查外部过滤器并检查对应于“pending:true”的“Pending”。必须使用哪个值?至少你必须像我在stackoverflow.com/questions/3989786/… 中描述的那样重置多重搜索过滤器。在了解了所有问题后,我决定从我的答案stackoverflow.com/questions/3981874/…中选择方式。我将外部过滤器与内部过滤器同步,这有助于避免冲突。
    • 如果您在服务器上使用数据,您可以在服务器端将 OrderStatus 解码为 1 和 0,而不是在客户端在 loadCompleted 中执行此操作(我也考虑过这一点并包括在内ok-soft-gmbh.com/jqGrid/CheckboxesWithVerticalHeaders.htm 代码的注释部分中的可能解决方案)。然而,您必须解决外部和内部过滤器之间的冲突问题。
    猜你喜欢
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 2021-10-14
    • 2011-02-25
    • 2018-12-25
    • 1970-01-01
    相关资源
    最近更新 更多