Oracle APEX:页面加载时动态操作添加交互式网格过滤器重复问题
解决Interactive Grid过滤器重复添加的问题
你遇到的核心问题是页面加载时多个动态操作同时触发newFilter函数,虽然你已经加了filterAlreadyExist的检查,但因为事件触发的并发性(或者说函数调用的时序间隙),导致第一个调用还没完成过滤器添加,第二个调用就执行了检查,误以为过滤器不存在,最终重复添加。
下面给你几个可行的解决思路:
1. 给newFilter加执行锁,避免并发调用
最简单的方式是给函数加一个临时锁,确保同一时间只有一个实例在执行,彻底避免并发判断误差。修改后的代码如下:
// 定义全局锁变量,初始为未执行状态 let isFilterProcessing = false; function newFilter(){ // 如果已有执行中的实例,直接返回 if(isFilterProcessing) return; isFilterProcessing = true; try { var vals = apex.item('P12_VALUE').getValue(); if(!(vals.includes('DI'))){ deleteExistingFilters('emp', 'IS_ON'); } if(vals.includes('DI')){ if(!filterAlreadyExist('emp', 'IS_ON')){ addFilter('emp', 'IS_ON','Y','EQ'); } } } finally { // 无论执行成功或失败,都释放锁 isFilterProcessing = false; } }
2. 合并动态操作,从根源减少触发次数
既然是修改多个控件导致多次change事件触发,你可以:
- 将多个控件的修改操作合并到同一个动态操作中,这样只会触发一次
newFilter调用,从源头避免重复。 - 或者给这些动态操作设置执行顺序优先级,在Oracle APEX的动态操作配置里调整顺序,让前一个操作完成后再执行下一个,避免同时触发。
3. 优化filterAlreadyExist的检查逻辑
有时候重复添加是因为过滤器的判断逻辑不够精准,比如漏了检查操作符、值等关键属性。你可以参考这个示例实现,确保检查逻辑覆盖所有必要维度:
function filterAlreadyExist(gridId, columnName){ const ig = apex.region(gridId).widget().interactiveGrid('getViews','grid'); const model = ig.model; const filters = model.getFilters(); // 精准匹配列名、操作符、过滤值 return filters.some(filter => filter.column === columnName && filter.operator === 'EQ' && filter.value === 'Y' ); }
4. 延迟执行,合并多次触发为一次
如果无法避免多次触发,可以用setTimeout延迟执行,让所有change事件都触发完成后,再统一执行一次过滤逻辑:
// 定义定时器变量,用于清除重复触发 let filterTimeout; function newFilter(){ // 清除之前的定时器,确保只执行最后一次触发的逻辑 clearTimeout(filterTimeout); // 延迟50ms执行,足够覆盖所有同步触发的事件 filterTimeout = setTimeout(() => { var vals = apex.item('P12_VALUE').getValue(); if(!(vals.includes('DI'))){ deleteExistingFilters('emp', 'IS_ON'); } if(vals.includes('DI')){ if(!filterAlreadyExist('emp', 'IS_ON')){ addFilter('emp', 'IS_ON','Y','EQ'); } } }, 50); }
你可以根据自己的场景选择最适合的方案,优先考虑合并动态操作或加执行锁的方式,这两种是最直接有效的。
内容的提问来源于stack exchange,提问作者Gorupria
相关产品推荐
相关产品推荐

