colDef中equals函数参数未定义及单元格编辑回滚问题咨询
问题一:equals函数参数为undefined的原因
首先,AG Grid调用equals时传入undefined,基本都和单元格值的获取/设置逻辑挂钩,常见场景有这几个:
默认编辑器不支持对象类型
如果你用的是AG Grid自带的文本编辑器,它本来是给字符串、数字这类简单类型设计的。当单元格绑定的是对象时,默认编辑器没法把用户输入转换成有效的新对象实例,编辑完成后返回的新值就是undefined,这时候equals自然会收到两个undefined参数。valueGetter/field配置有问题
检查下你的colDef:如果用了valueGetter但它返回undefined,或者field对应的对象属性根本不存在,AG Grid在对比新旧值时就会传入undefined。可以先打印下单元格绑定的原始数据,确认对象的Id属性是否存在。取消编辑触发的异常调用
要是用户在编辑中途按Esc取消,AG Grid也可能触发equals对比,但此时新值还没被正确设置,也会出现参数为undefined的情况。你可以结合日志的触发时机,看看是不是这种场景。
问题二:取消单元格数据变更的正确方式
你想用onCellValueChanged做异步校验后回滚,思路是对的,但有几个细节要调整,还有更严谨的实现方式:
先别依赖equals控制事件触发
你的equals是用来判断新旧值是否“相等”,从而决定要不要触发onCellValueChanged。但你的需求是不管值是否相等,都要发起异步请求校验,所以这个equals的设计反而会干扰事件触发,建议先注释掉它,确保onCellValueChanged能正确拿到新旧值。
正确的回滚步骤
保存旧值时记得深拷贝
因为是对象类型,直接赋值会导致新旧值指向同一个引用,后续回滚会出问题,所以要深拷贝:gridOptions.onCellValueChanged = (event) => { // 深拷贝旧值,避免后续被修改 const oldValue = JSON.parse(JSON.stringify(event.oldValue)); const newValue = event.newValue; const targetNode = event.node; const targetColKey = event.column.colId; // 发起异步请求 fetch('/your-api-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newValue) }) .then(res => { if (!res.ok) throw new Error('请求失败'); // 请求成功,无需额外操作 }) .catch(err => { console.error('回滚原因:', err); // 回滚到旧值 gridOptions.api.setCellValue(targetNode, targetColKey, oldValue); // 强制刷新单元格确保显示正确 gridOptions.api.refreshCells({ rowNodes: [targetNode], columns: [event.column], force: true }); }); };避免循环触发事件
调用setCellValue会再次触发onCellValueChanged,所以要加个标记拦截循环:let isRollingBack = false; gridOptions.onCellValueChanged = (event) => { if (isRollingBack) { isRollingBack = false; return; } // ... 前面的逻辑 .catch(err => { isRollingBack = true; gridOptions.api.setCellValue(targetNode, targetColKey, oldValue); // ... 刷新逻辑 }); };进阶方案:编辑前拦截(可选)
如果不想让用户看到“临时变更后又回滚”的体验,可以用onCellEditingStopped在编辑结束前校验,失败就阻止提交:gridOptions.onCellEditingStopped = (event) => { const editor = event.api.getCellEditorInstances({ rowNodes: [event.node], columns: [event.column] })[0]; const newValue = editor.getValue(); const oldValue = event.node.data[event.column.field]; fetch('/your-api-endpoint', { ... }) .catch(() => { // 恢复编辑器的旧值 editor.setValue(oldValue); event.api.refreshCells({ rowNodes: [event.node], columns: [event.column] }); }); };
内容的提问来源于stack exchange,提问作者sebius

