D365中JS动态生成的选项集无法选中选项问题求助
问题现象
- 自定义选项集字段通过代码动态填充实体列表成功,但选中选项后字段无法赋值、选项不保持选中状态
- 为该字段配置的
OnChangeOfEntity事件从未触发
问题根源
选项值与后端定义不兼容
动态添加选项时使用i+1作为value,但Dynamics 365要求前端选项值必须与该字段在Dataverse中预先定义的选项值匹配。如果后端没有对应值,系统无法识别选中操作,导致无法赋值和触发事件。OnChange事件注册逻辑冗余混乱
OnChangeOfEntity本身是表单配置的字段OnChange事件处理程序,但内部又调用optionSetField.addOnChange()添加额外处理器,既冗余又会导致事件触发逻辑失效。重复加载的潜在状态异常
表单重复加载(如快速切换表单)时,重复清空添加选项可能导致控件状态异常。
修复方案
1. 修正选项值生成逻辑
使用实体的MetadataId作为选项值(唯一且稳定),确保前端选项与后端字段兼容:
// 表单加载事件处理函数 function OnLoad(executionContext) { var formContext = executionContext.getFormContext(); var optionSetField = formContext.getAttribute("zzz_entity"); GetEntityDefinitions().then(function(entities) { // 清空现有选项 optionSetField.controls.forEach(function(control) { control.clearOptions(); }); // 添加空选项(可选,根据业务需求调整) optionSetField.controls.forEach(function(control) { control.addOption({ text: "", value: null }); }); // 用实体MetadataId作为选项值添加选项 entities.forEach(function(entity) { var option = { text: entity.LogicalName, value: entity.MetadataId }; optionSetField.controls.forEach(function(control) { control.addOption(option); }); }); }).catch(function(error) { console.error("加载实体列表失败:", error); }); } // 获取包含MetadataId的实体定义 function GetEntityDefinitions() { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.open("GET", Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/EntityDefinitions?$select=LogicalName,MetadataId", true); req.setRequestHeader("OData-MaxVersion", "4.0"); req.setRequestHeader("OData-Version", "4.0"); req.setRequestHeader("Accept", "application/json"); req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); req.onreadystatechange = function() { if (this.readyState === 4) { req.onreadystatechange = null; if (this.status === 200) { var results = JSON.parse(this.response); resolve(results.value); } else { reject(new Error('请求失败,状态码: ' + this.status + ', 状态信息: ' + this.statusText)); } } }; req.send(); }); }
2. 修正OnChange事件处理逻辑
直接在OnChangeOfEntity中编写业务逻辑,无需额外注册处理器,确保函数直接绑定到字段的OnChange事件:
function OnChangeOfEntity(executionContext) { var formContext = executionContext.getFormContext(); var optionSetField = formContext.getAttribute("zzz_entity"); var selectedValue = optionSetField.getValue(); if (selectedValue != null) { var selectedText = optionSetField.getText(); console.log("选中的实体值: " + selectedValue); console.log("选中的实体名称: " + selectedText); GetEntityCollectionName(selectedText) .then(function(entityCollectionName) { formContext.getAttribute("zzz_entityCollection").setValue(entityCollectionName); }) .catch(function(error) { console.error(error); }); } else { console.log("zzz_entity字段未选中任何选项"); formContext.getAttribute("zzz_entityCollection").setValue(null); } } // 获取实体集合名称(移除冗余变量声明) function GetEntityCollectionName(entityName) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.open("GET", Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/EntityDefinitions?$select=LogicalName,CollectionName&$filter=LogicalName eq '" + entityName + "'", true); req.setRequestHeader("OData-MaxVersion", "4.0"); req.setRequestHeader("OData-Version", "4.0"); req.setRequestHeader("Accept", "application/json"); req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); req.onreadystatechange = function() { if (this.readyState === 4) { req.onreadystatechange = null; if (this.status === 200) { var results = JSON.parse(this.response); if (results.value.length > 0) { var entityCollectionName = results.value[0].CollectionName; resolve(entityCollectionName); } else { reject(new Error('未找到指定实体')); } } else { reject(new Error('请求失败,状态码: ' + this.status + ', 状态信息: ' + this.statusText)); } } }; req.send(); }); }
3. 额外检查项
- 确认
zzz_entity字段在Dataverse中为可编辑选项集,无表单级只读/禁用设置 - 在表单编辑器中,确保
OnLoad绑定到表单加载事件、OnChangeOfEntity绑定到zzz_entity字段的OnChange事件,且传递执行上下文作为第一个参数选项已勾选 - 测试前清除浏览器缓存,避免旧代码残留
内容的提问来源于stack exchange,提问作者J.S.Orris
相关产品推荐
相关产品推荐

