You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jqxGrid使用addfilter函数自定义派生列过滤器失败求助

jqxGrid 合并列过滤问题

我需要在jqxGrid中合并firstname和lastname列为name列,实现用户对name列过滤时,实际搜索firstname或lastname字段。最终要通过updatebounddata将过滤信息发送到服务器,基于datafields返回对应结果,但需要把过滤器的datafields替换为firstname和lastname。

我编写了示例代码,原本期望将name过滤器替换为firstname和lastname过滤器后,const ex和const ex1的值会不同,但实际没有任何更新效果。


HTML代码

<div id='jqxWidget'>
  <div id="jqxgrid"></div>
</div>

原始JavaScript代码

var data = generatedata(500);

var source = {
  localdata: data,
  datafields: [
    {
      name: "firstname",
      type: "string"
    },
    {
      name: "lastname",
      type: "string"
    },
    {
      name: "name",
      type: "string",
      map: "firstname, lastname"
    }
  ],
  datatype: "array",
  beforeLoadComplete: function (records) {
    const data = new Array();

    for (var i = 0; i < records.length; i++) {
      const current = records[i];
      current.name = `${current.firstname} ${current.lastname}`;
      data.push(current);
    }

    return data;
  },
  filter: function (filters, b, c) {
    updateFilters();
  }
};

var adapter = new $.jqx.dataAdapter(source);

$("#jqxgrid").jqxGrid({
  width: "100%",
  theme: "energyblue",
  source: adapter,
  filterable: true,
  showfilterrow: true,
  columns: [
    {
      text: "Name",
      datafield: "name",
      columngroup: "Name",
      width: 1190
    }
  ]
});

function updateFilters() {

  // Take snapshot of active filters
  debugger;

  const ex = $("#jqxgrid").jqxGrid("getfilterinformation");

  if (ex.length > 1) {
    $("#jqxgrid").jqxGrid("updatebounddata");
  } else {
    const activeFilters = [];

    $.each(
      $("#jqxgrid").jqxGrid("getfilterinformation"),
      (index, filterInfo) => {
        if (filterInfo.datafield === "name") {
          let value = filterInfo.filter.filtervalue
            ? filterInfo.filter.filtervalue
            : filterInfo.filter.getfilters()[0].value;

          let condition = filterInfo.filter.filtervalue
            ? filterInfo.filter.comparisonoperator
            : filterInfo.filter.getfilters()[0].condition;

          activeFilters.push({
            columnName: "firstname",
            filterValue: value.toLowerCase(),
            filterCondition: condition.toLowerCase()
          });

          activeFilters.push({
            columnName: "lastname",
            filterValue: value.toLowerCase(),
            filterCondition: condition.toLowerCase()
          });
        }
      }
    );

    //$("#jqxgrid").jqxGrid("clearfilters");
    // $("#jqxgrid").jqxGrid("removefilter", 'name');

    // Update bound data / reset init row etc

    // Reapply filters
    activeFilters.forEach((filter) => {
      const filtergroup = new $.jqx.filter();
      filtergroup.operator = "or";
      const filtervalue = filter.filterValue;
      const filtercondition = filter.filterCondition;
      const filter1 = filtergroup.createfilter(
        "stringfilter",
        filtervalue,
        filtercondition
      );

      filtergroup.addfilter(1, filter1);
      $("#jqxgrid").jqxGrid("addfilter", filter.columnName, filtergroup);
    });

    const ex1 = $("#jqxgrid").jqxGrid("getfilterinformation");

    $("#jqxgrid").jqxGrid("updatebounddata");

    //$("#jqxgrid").jqxGrid("refreshfilterrow");
  }
}

问题分析与修正方案

核心问题

  1. 未清除原过滤器:代码注释掉了清除name列过滤器的逻辑,导致原过滤器依然存在,新添加的firstname/lastname过滤器无法替换它,getfilterinformation返回的结果自然不会变化。
  2. 循环触发事件:在source.filter事件中调用updateFilters,而updatebounddata又会再次触发filter事件,形成无限循环。
  3. 过滤器逻辑冗余:单个列的过滤器不需要设置or操作符,应该将firstname和lastname的过滤器合并为一个or组,或者直接添加两个过滤器后确保逻辑正确。

修正后的JavaScript代码

var data = generatedata(500);

var source = {
  localdata: data,
  datafields: [
    { name: "firstname", type: "string" },
    { name: "lastname", type: "string" },
    { 
      name: "name", 
      type: "string", 
      map: "firstname, lastname",
      // 自定义过滤逻辑,直接处理name列的过滤请求
      filter: function(value, row) {
        const searchVal = value.toLowerCase();
        return row.firstname.toLowerCase().includes(searchVal) || row.lastname.toLowerCase().includes(searchVal);
      }
    }
  ],
  datatype: "array",
  beforeLoadComplete: function (records) {
    return records.map(current => ({
      ...current,
      name: `${current.firstname} ${current.lastname}`
    }));
  }
};

var adapter = new $.jqx.dataAdapter(source);

$("#jqxgrid").jqxGrid({
  width: "100%",
  theme: "energyblue",
  source: adapter,
  filterable: true,
  showfilterrow: true,
  columns: [
    {
      text: "Name",
      datafield: "name",
      columngroup: "Name",
      width: 1190
    }
  ],
  // 改用filterrow事件处理,避免循环调用
  filterrow: function() {
    $("#jqxgrid").jqxGrid("updatebounddata");
  }
});

关键改动说明

  1. 自定义列过滤逻辑:在name列的datafields中添加filter函数,直接判断firstname或lastname是否包含搜索值,无需替换过滤器的datafields,更简洁高效。
  2. 简化数据处理:用map替代原循环构建数据,代码更简洁。
  3. 替换事件触发时机:改用filterrow事件触发数据更新,避免filter事件的循环调用问题。

如果需要将过滤参数发送到服务器,可以在source.beforeSend事件中修改请求参数,将name的过滤条件转换为firstname和lastname的OR条件:

var source = {
  // ... 其他配置
  beforeSend: function(xhr, settings) {
    // 获取当前过滤器信息
    const filterInfo = $("#jqxgrid").jqxGrid("getfilterinformation");
    if (filterInfo.length > 0 && filterInfo[0].datafield === "name") {
      const filter = filterInfo[0].filter;
      const value = filter.filtervalue || filter.getfilters()[0].value;
      const condition = filter.comparisonoperator || filter.getfilters()[0].condition;
      
      // 构建服务器需要的过滤参数,替换name为firstname和lastname的OR条件
      const newFilter = {
        groupoperator: "or",
        filters: [
          { datafield: "firstname", condition, value },
          { datafield: "lastname", condition, value }
        ]
      };
      
      // 修改请求数据,这里根据实际请求格式调整
      const data = JSON.parse(settings.data);
      data.filter = newFilter;
      settings.data = JSON.stringify(data);
    }
  }
};

内容的提问来源于stack exchange,提问作者heyNow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:03:13