如何用JavaScript编写可识别触发类型的Dynamics表单通用校验函数
Dynamics CRM 共用校验函数实现方案
下面提供两种可落地的实现方式,以及对应的最佳实践建议:
方案1:通过事件上下文特征自动判断
Dynamics 表单的executionContext(执行上下文)的事件参数对象在不同事件下有专属方法,可以直接用来区分触发场景:
- onChange事件的参数对象存在
getFieldName()方法,可返回触发变更的字段名 - onSave事件的参数对象存在
preventDefault()方法,可阻止表单保存行为
示例代码:
function commonValidation(executionContext) { const formContext = executionContext.getFormContext(); const eventArgs = executionContext.getEventArgs(); let eventType = ''; // 判断事件类型 if (typeof eventArgs.getFieldName === 'function') { eventType = 'onChange'; } else if (typeof eventArgs.preventDefault === 'function') { eventType = 'onSave'; } // ########## 公共校验逻辑 ########## let validatePass = true; // 这里写你统一的校验规则,比如字段必填、格式校验等 const age = formContext.getAttribute("crxxx_age").getValue(); if (age && age < 18) { formContext.getControl("crxxx_age").setNotification("年龄不能小于18岁", "age_error"); validatePass = false; } else { formContext.getControl("crxxx_age").clearNotification("age_error"); } // ########## 不同事件的后续分支逻辑 ########## if (eventType === 'onChange') { // onChange 后续处理:比如联动更新其他字段、显示隐藏控件等 if (validatePass) { formContext.getAttribute("crxxx_is_adult").setValue(age >= 18); } } else if (eventType === 'onSave') { // onSave 后续处理:校验不通过则阻止保存 if (!validatePass) { eventArgs.preventDefault(); } } }
使用说明:注册onChange和onSave事件时,都勾选「将执行上下文作为第一个参数传递」选项即可。
方案2:注册事件时主动传入类型标记(更推荐)
这种方式不需要依赖事件参数的原生特性,兼容性和可维护性更强,不会因为Dynamics版本更新导致判断失效:
- 编写共用函数时预留类型参数
示例代码:
function commonValidation(executionContext, eventType) { const formContext = executionContext.getFormContext(); const eventArgs = executionContext.getEventArgs(); // ########## 公共校验逻辑 ########## let validatePass = true; // 同方案1的统一校验逻辑 // ########## 不同事件的后续分支逻辑 ########## if (eventType === 'onChange') { // onChange 后续处理 } else if (eventType === 'onSave') { // onSave 后续处理,校验不通过阻止保存 if (!validatePass) { eventArgs.preventDefault(); } } }
- 注册事件时传入对应参数:
- 注册onChange事件时,在「函数参数」的「可选参数」输入框填写
'onChange' - 注册onSave事件时,在「函数参数」的「可选参数」输入框填写
'onSave'
注意都需要勾选「将执行上下文作为第一个参数传递」选项。
最佳实践建议
如果后续分支逻辑复杂度会逐渐升高,可以把公共校验逻辑单独抽为工具函数,再分别写两个入口函数调用:
// 公共校验工具函数,返回校验是否通过 function validateForm(formContext) { let pass = true; // 所有校验逻辑写在这里 return pass; } // onChange 入口 function onChangeHandler(executionContext) { const formContext = executionContext.getFormContext(); const pass = validateForm(formContext); // onChange 后续逻辑 } // onSave 入口 function onSaveHandler(executionContext) { const formContext = executionContext.getFormContext(); const eventArgs = executionContext.getEventArgs(); const pass = validateForm(formContext); if (!pass) { eventArgs.preventDefault(); } }
这种拆分方式符合单一职责原则,后续维护成本更低,不会因为分支越来越多导致函数过于臃肿。
内容的提问来源于stack exchange,提问作者Etto
相关产品推荐
相关产品推荐

