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

Ag-Grid V18.1中onCellFocus与排序功能兼容异常问题咨询

Ag-Grid V18.1 排序后onCellFocus事件失效:DOM焦点不匹配问题修复

我们的应用基于自定义Ag-Grid V18.1组件开发,当onCellFocus事件与排序功能组合使用时出现异常——排序后聚焦单元格时无法正确定位DOM元素,焦点设置失效。核心原因是排序后网格行的rowIndex会发生变化,原代码中通过e.column.getId() + e.rowIndex拼接DOM ID的方式,会导致定位到的元素和实际聚焦的单元格不匹配。

原问题代码

onCellFocused = (e) => {        
    if (e.rowIndex !== null) {
        const selectedData = this.gridChild.getSelectedRows();       
        let pin = 0;
        if(selectedData !== undefined) { 
            selectedData.map(row => {
                pin = row.pin;
            });
        }

        this.bindTechSpecLineItems(pin, e);

        if(e.column.getId() === 'expenseDate' || e.column.getId() === 'expenseDescription') {
            this.setState({ isReloadGrid : true });
        } else {
            this.setState({ isReloadGrid : false });
        }

        if(document.getElementById(e.column.getId() + e.rowIndex) !== null) {
            if(document.getElementById(e.column.getId() + e.rowIndex).type === 'text') {                    
                document.getElementById(e.column.getId() + e.rowIndex).select();     
            } else if(document.getElementById(e.column.getId() + e.rowIndex).type === 'select-one') {
                if(e.forceBrowserFocus) 
                    document.getElementById(e.column.getId() + e.rowIndex).focus();
                else
                    document.getElementById(e.column.getId() + e.rowIndex).click();
            } else {                    
                document.getElementById(e.column.getId() + e.rowIndex).focus();                    
            }
        } 
    }
}

表头配置

{
    "rowSelection": 'multiple',         
    "pagination": false,
    "enableFilter": false,
    "enableSorting": true,          
    "searchable": false,
    "gridActions": true,
    "gridTitlePanel": false,
    "headerHeight":40
}

修复方案

核心思路是放弃依赖rowIndex定位DOM,改用Ag-Grid提供的API获取单元格实例,同时优化行数据的获取逻辑:

onCellFocused = (e) => {        
    if (e.rowIndex === null) return;

    // 直接从当前聚焦行获取pin,无需遍历所有选中行
    const focusedRowData = e.rowData;
    const pin = focusedRowData?.pin || 0;

    this.bindTechSpecLineItems(pin, e);

    // 简化状态更新逻辑
    const shouldReload = ['expenseDate', 'expenseDescription'].includes(e.column.getId());
    this.setState({ isReloadGrid: shouldReload });

    // 用Ag-Grid API获取单元格DOM,彻底摆脱rowIndex依赖
    const cellRenderer = e.api.getCellRendererInstances({
        rowNodes: [e.node],
        columns: [e.column]
    })[0];
    
    if (!cellRenderer) return;
    const cellDom = cellRenderer.getGui();
    const inputElement = cellDom.querySelector('input, select');
    
    if (!inputElement) return;

    // 根据元素类型处理焦点/选中逻辑
    if (inputElement.type === 'text') {
        inputElement.select();
    } else if (inputElement.type === 'select-one') {
        e.forceBrowserFocus ? inputElement.focus() : inputElement.click();
    } else {
        inputElement.focus();
    }
}

关键修改点

  1. 行数据获取优化:直接从e.rowData拿到当前聚焦行的pin,不用遍历选中行(原逻辑会覆盖pin值,只保留最后一个选中行的pin,逻辑错误)
  2. DOM定位方式替换:用getCellRendererInstances通过rowNode和column获取单元格实例,再通过getGui()拿到DOM元素,排序后依然能精准定位
  3. 简化条件判断:用数组includes替代多条件判断,代码更简洁
  4. 避免重复DOM查询:只查询一次DOM元素,提升性能

额外优化建议

为了让Ag-Grid更稳定地识别行,建议在gridOptions中配置行唯一标识:

// 添加到表头配置中
"getRowId": params => params.data.pin // 假设pin是每行的唯一ID

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:47:44