Oracle APEX Change事件中如何获取Interactive Grid列值以校验唯一性
Oracle Apex 20.2 Interactive Grid 条码防重复输入解决方案
核心问题原因说明
- 你拿到旧值是因为Change事件触发时,IG的model层还未完成新值的同步,通过选中行去model里取值自然拿到的是更新前的旧值
- 回车触发两次事件是APEX IG的默认行为:回车会先提交当前行的编辑,再自动创建并跳转到下一行新行,新行的输入框也会触发一次Change事件
最简修复方案
优先直接从触发事件的输入框拿最新值,不需要通过IG model取数,避免同步延迟问题,同时加逻辑过滤无效的触发场景:
// 直接取输入框的最新值,不需要走model查询 const newBarcode = this.triggeringElement.value.trim(); // 空值直接跳过校验,过滤回车自动生成的新行触发的无效事件 if (!newBarcode) return; // 校验重复:优先用你已有的全局数组,也可以实时遍历IG所有行校验 if (window.barcodes.includes(newBarcode)) { apex.message.showErrors([{ type: "error", location: "page", message: "输入的条码已存在于列表中", unsafe: false }]); // 可选:清空当前输入框的值避免提交错误数据 this.triggeringElement.value = ''; return; } // 如果需要同步旧值做对比,可以用以下方式取旧值 const grid = apex.region('LINES').widget().interactiveGrid('getViews', 'grid'); const model = grid.model; // 通过触发元素获取当前行记录,比通过选中行更准确,避免行切换导致的选不到问题 const record = grid.getRecord(this.triggeringElement); const oldBarcode = model.getValue(record, 'BARCODE')?.trim() || ''; // 只有值真的发生变更时才更新全局数组 if (newBarcode !== oldBarcode) { // 把旧值从全局数组里删掉 if (oldBarcode) { const index = window.barcodes.indexOf(oldBarcode); if (index > -1) window.barcodes.splice(index, 1); } // 加入新值 window.barcodes.push(newBarcode); // 手动同步更新到model,避免后续取值异常 model.setValue(record, 'BARCODE', newBarcode); }
优化方案(无需维护全局数组)
如果不想维护全局数组避免出现数据不同步的问题,可以直接实时遍历IG里的所有记录校验:
const grid = apex.region('LINES').widget().interactiveGrid('getViews', 'grid'); const model = grid.model; const currentRecord = grid.getRecord(this.triggeringElement); const newBarcode = this.triggeringElement.value.trim(); if (!newBarcode) return; let isDuplicate = false; // 遍历所有行记录校验 model.forEach(function(record) { // 跳过当前正在编辑的行本身 if (record === currentRecord) return; const existBarcode = model.getValue(record, 'BARCODE')?.trim() || ''; if (existBarcode === newBarcode) { isDuplicate = true; return false; } }); if (isDuplicate) { apex.message.showErrors([{ type: "error", location: "page", message: "输入的条码已存在于列表中", unsafe: false }]); this.triggeringElement.value = ''; }
额外注意事项
- 动态动作的触发事件选Interactive Grid > 列变更,不要用通用的Change事件,适配性更好,不会触发多余的事件
- 如果还是出现回车触发两次的问题,可以在代码里加100ms的防抖处理,过滤连续的无效触发
内容的提问来源于stack exchange,提问作者Superdooperhero
相关产品推荐
相关产品推荐

