jqGrid:使用多种方法过滤数据

时间:2010-10-20 02:31:22

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

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

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

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 as teh customer want it

客户想要使用两种方法或两者同时过滤网格中的数据:

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

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

总结一下我应该:

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

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:18)

我理解这个要求非常好。在最后的情况下,我在 jqGrid中使用了复选框。在jqGrid中获取信息的最大好处不仅在于易于搜索的可能性。如果数据位于网格之外,您将在右侧窗格中显示订单详细信息仅针对所选行。因此,用户将没有那么好的概述数据。

为了能够在没有永久水平滚动的情况下在表格中放置许多复选框,我使用Vertical text inside table headers using a JavaScript-based SVG library中描述的技术旋转了列的标题。此旋转在IE中看起来并不完美,但在其他浏览器中工作得很完美。

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

因为使用想要使用multiplesearch:true我必须提到jQuery.clone中的一个错误,它跟随所有版本的IE浏览器中jqGrid多搜索中的错误。如果您将更多定义为一个搜索过滤器,则仅使用第一个过滤器,因为所有其他过滤器的操作字段将被读取为undefined。很遗憾,但是刚刚发布的jQuery 1.4.3中也没有修复这个bug。为了能够使用multiplesearch:true,您可以使用Jiho Han on trirand.com forum的解决方法建议。

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

alt text

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

alt text

相应的代码:

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。现在看起来像 alt text

它更贴近您的需求。

答案 1 :(得分:0)

正如后续跟进一样,我在这里包含了另一种方法,我发现它可以获得相同的结果。

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

这是一个样本

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

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

快乐的编码!