Dynamics CRM 2016新建表单加载完成校验及字段锁定方案问询
解决Dynamics CRM 2016新建表单onLoad时字段值为Null的问题
这个场景我太熟悉了!在CRM 2016的新建表单里,onLoad事件触发的时机是表单DOM结构渲染完成,但像lookup这类字段的初始值(尤其是从父记录传递过来的默认值)往往是通过异步请求加载的,会晚于onLoad事件完成,所以你直接取值会拿到null。下面给你两种靠谱的解决方案,结合你的代码修改:
方案一:轮询等待目标字段加载完成
通过递归+定时器轮询目标字段的加载状态,直到字段加载完成再执行你的业务逻辑,避免异步加载的时间差问题。
修改后的完整代码:
function OnLoad() { try { if (formType == formTypes.Create) { // 启动轮询,等待portfolio字段加载完成后执行检查逻辑 waitForFieldLoad("protfolioid", checkNeedsUnique); } } catch (e) { frameworkGlobal.reportExceptionToServer(e); } }; // 辅助函数:等待指定字段加载完成 function waitForFieldLoad(fieldName, callback) { var attribute = Xrm.Page.getAttribute(fieldName); // 检查字段存在且已加载,或者设置最大轮询次数防止无限循环 if (attribute && attribute.isLoaded()) { callback(); // 重置轮询计数 window.fieldLoadAttempts = 0; } else { var currentAttempt = window.fieldLoadAttempts || 0; if (currentAttempt < 10) { window.fieldLoadAttempts = currentAttempt + 1; // 每500ms检查一次,可根据实际情况调整间隔 setTimeout(function() { waitForFieldLoad(fieldName, callback); }, 500); } else { console.log(`字段${fieldName}加载超时,可在此添加异常处理`); } } } function checkNeedsUnique(){ var portfolio = Xrm.Page.getAttribute("protfolioid").getValue(); // 增加兜底判断,防止极端情况仍拿不到值 if (!portfolio || !portfolio[0] || !portfolio[0].id) { console.log("未获取到portfolio字段值"); return; } var filter = "needsSet?$select=needsId&$filter=protfolioid/Id eq guid'" + portfolio[0].id + "' and statecode/Value eq 0"; var ret = frameworkGlobal.RetrieveMultiple(filter, false); if(!!ret && ret.length > 0){ disableAllFields(); } }
方案二:监听字段的Load事件
CRM 2016支持给字段绑定load事件,当字段完成数据加载时自动触发回调逻辑,比轮询更精准。
修改后的完整代码:
function OnLoad() { try { if (formType == formTypes.Create) { var portfolioAttr = Xrm.Page.getAttribute("protfolioid"); if (portfolioAttr) { // 绑定字段加载完成事件 portfolioAttr.addOnLoad(checkNeedsUnique); // 如果字段已经提前加载完成,直接执行一次逻辑 if (portfolioAttr.isLoaded()) { checkNeedsUnique(); } } } } catch (e) { frameworkGlobal.reportExceptionToServer(e); } }; function checkNeedsUnique(){ var portfolio = Xrm.Page.getAttribute("protfolioid").getValue(); if (!portfolio || !portfolio[0] || !portfolio[0].id) { return; } var filter = "needsSet?$select=needsId&$filter=protfolioid/Id eq guid'" + portfolio[0].id + "' and statecode/Value eq 0"; var ret = frameworkGlobal.RetrieveMultiple(filter, false); if(!!ret && ret.length > 0){ disableAllFields(); } }
关键说明
- 核心原因:CRM表单的
onLoad事件仅保证DOM结构就绪,字段数据(尤其是关联lookup、默认值)是异步加载的,所以会存在时间差。 - 两种方案都加入了
null兜底判断,避免极端情况下的报错。 - 轮询的次数和间隔可以根据你的系统性能调整,500ms和10次是比较保守的设置。
内容的提问来源于stack exchange,提问作者Damkulul
相关产品推荐
相关产品推荐

