Oracle APEX:如何通过Ajax从后端更新交互式网格并执行DML操作
问题
我用两个Interactive Grid展示数据,想要同时实现两个需求:一是正常展示数据,二是通过后端Ajax对选中的网格行执行DML操作。之前用SQL和PL/SQL尝试实现,但没达到预期效果。我写的JavaScript代码如下:
function setCellsToReadOnly () { var grid = apex.region("readonly_emp_ig_id").widget().interactiveGrid("getViews","grid"); var model = grid.model; var recordVal; model.forEach(function(record, index, id) { // getFieldKey返回字段名对应的索引,用于访问记录的该字段 recordVal = record[model.getFieldKey("VALIDATED")]; var meta = model.getRecordMetadata(id); var fields = meta.fields; if (!fields) { fields = meta.fields = {}; } if (!fields["EMPNO"] || !fields["JOB"] || !fields["MGR"] || !fields["ENAME"] ) { fields["EMPNO"] = {}; fields["JOB"] = {}; fields["MGR"] = {}; fields["ENAME"] = {}; } // 获取recordVal的第一个键对应的值 if (recordVal[Object.keys(recordVal)[0]] === 'Y') { // 设置为只读 fields["EMPNO"].ck = 1; fields["JOB"].ck = 1; fields["MGR"].ck = 1; fields["ENAME"].ck = 1; // 触发元数据变更 model.metadataChanged(id); } else { fields["EMPNO"].ck = ""; fields["JOB"].ck = ""; fields["MGR"].ck = ""; fields["ENAME"].ck = ""; model.metadataChanged(id); } }); }
解决思路与调整方案
1. 修正只读逻辑的潜在问题
原代码中通过Object.keys(recordVal)[0]取值的方式不可靠,因为对象键的顺序不固定。APEX IG提供了更安全的字段值获取方法model.getValue(record, 字段名),建议替换:
// 替换原recordVal相关代码 var validatedVal = model.getValue(record, "VALIDATED"); // 直接判断值即可 if (validatedVal === 'Y') { // 设置只读逻辑不变 }
另外,设置只读属性时,官方更推荐使用fields[字段名].readonly = true而非ck=1,兼容性更好:
fields["EMPNO"].readonly = true; fields["JOB"].readonly = true; // ...其他字段同理
2. 实现选中行的后端Ajax DML操作
要完成选中行的DML处理,按以下步骤操作:
- 获取选中行:通过IG的API获取选中记录
var grid = apex.region("readonly_emp_ig_id").widget().interactiveGrid("getViews","grid"); var model = grid.model; var selectedRecords = grid.getSelectedRecords(); - 提取主键信息:从选中记录中取出需要传递给后端的主键(比如EMPNO)
var selectedEmpIds = selectedRecords.map(function(record) { return model.getValue(record, "EMPNO"); }); - 调用后端Ajax过程:使用APEX自带的
apex.server.process提交请求,传递选中的主键列表apex.server.process("PROCESS_SELECTED_EMP", { // x01为自定义参数,后端可通过apex_application.g_x01获取 x01: JSON.stringify(selectedEmpIds) }, { success: function(response) { // 操作成功后刷新IG,更新数据 apex.region("readonly_emp_ig_id").refresh(); apex.message.showSuccess("操作完成"); }, error: function(xhr) { apex.message.showErrors([{ type: "error", message: "操作失败,请重试" }]); } }); - 后端PL/SQL处理:创建名为
PROCESS_SELECTED_EMP的Ajax回调过程,解析传入的JSON参数并执行DMLPROCEDURE process_selected_emp IS l_emp_ids apex_t_varchar2; BEGIN l_emp_ids := apex_string.split(json_value(apex_application.g_x01, '$'), ','); -- 示例:执行删除操作,根据实际需求替换为INSERT/UPDATE DELETE FROM emp WHERE empno IN (SELECT column_value FROM TABLE(l_emp_ids)); COMMIT; EXCEPTION WHEN OTHERS THEN apex_error.raise_error(p_message => '处理失败:' || SQLERRM); END;
3. 确保函数正确触发
将setCellsToReadOnly函数绑定到IG的初始化事件上,可通过页面的动态动作实现:
- 新建动态动作,事件选择“页面加载完成”或“Interactive Grid - 初始化后”
- 动作选择“执行JavaScript代码”,调用
setCellsToReadOnly();
内容的提问来源于stack exchange,提问作者Rao Atif
相关产品推荐
相关产品推荐

