简体中文
form.render.before
约 1886 字大约 6 分钟
2025-11-24
该钩子在渲染对象表单之前调用,此时不建议对表单数据执行update的相关操作,比如更新从对象数据。 表单渲染前执行额外的动作,包含且不限于以下功能:
自定义对象表单字段展示
自定义按钮
自定义标题
自定义视图
自定义提交成功后回调函数
自定义拦截按钮回调函数
自定义字段值变更前拦截函数
参数
| 参数 | 说明 | 类型 |
|---|---|---|
| 通用参数 | 详见 | -- |
| objApiName | 主对象apiName | String |
| recordType | 主对象业务类型 | String |
| masterData | 主对象数据 | String |
| details | 当前从对象数据(一般仅当复制、映射、编辑等来源有值) | Object |
| BaseComponents | 底层基础字段组件(所有扩展字段组件的基类,如果需要对表单字段进行扩展,需要用到此参数) | Object |
返回结果
| 参数 | 说明 | 类型 | 默认值 | |
|---|---|---|---|---|
| title | 表单标题(示例) | String | -- | |
| buttons | 表单操作按钮(示例) | Object | -- | |
| fieldEditBeforeCallBacks | 字段编辑之前自定义回调函数(仅支持查找关联字段)(示例) | Array | -- | |
| footerSlot | 表单底部插槽(示例) | 定义表单底部区域 | Array | -- |
| isSkipLayoutFieldStateCheck | 是否跳过表单底层对必填字段不能通过UI函数设置只读状态的控制 | Boolean | false | |
| components | 自定义字段组件(示例) | Object | -- | |
| mdSwitchCallBack | 从对象切换回调 | Function | -- | |
| beforeUIAction | 按钮执行之前的回调函数(示例) | Function | -- | |
| cancelCallBack | 取消按钮回调函数 | Function | -- | |
| submitSuccessCallBack | 提交数据成功之后回调函数 | Function | -- | |
| beforeSaveDraft | 保存草稿之前按钮回调函数 | Function | -- | |
| no_support_draft | 是否支持保存草稿 | Boolean | false | |
| groupSlots | 分组扩展(示例) | Array | -- |
buttons
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| del | 删除指定按钮 | Array | -- |
| add | 添加自定义按钮 | Array | -- |
| reset | 重置按钮名称和行为 | Array | -- |
基础示例
自定义标题
export default class Plugin {
apply() {
return [{
event: 'form.render.before',
functional: this.formRenderBefore.bind(this)
}]
}
formRenderBefore(plugin, context) {
return Promise.resolve({
title: '自定义标题'
})
}
}自定义按钮
export default class Plugin {
apply() {
return [{
event: 'form.render.before',
functional: this.formRenderBefore.bind(this)
}]
}
formRenderBefore(context, plugin) {
return Promise.resolve({
buttons: {
// 新增【自定义按钮】
add: [{
action: '',//可填可不填,如果需要根据数据动态调整按钮状态,则要填写。
label: '一键查询报价',
callback: () => {
let newContext = plugin.api.pluginServiceFactory();
let masterData = newContext.dataGetter.getMasterData();//获取到主表单数据
this.queryBusinessData(masterData).then(queryData => {
newContext.dataUpdater.updateMaster(queryData);//更新数据
newContext.end();
})
}
}],
// 删除【提交并新建】按钮
del: ['submitAndCreate'],
// 重置【提交按钮】的名称为【保存】
reset: [{
action: 'submit',
label: '保存'
}]
}
})
}
queryBusinessData(masterData) {
//此处模拟查询数据,实际应用中,应该是自己调接口
return new Promise(resolve => {
let queryData = {};
//price__c discount__c为要更新字段的api_name
//模拟接口逻辑判断表单上某个字段的值,返回不同的字段值
if(masterData.name === '北京') {
queryData.price__c = 1000;
queryData.discount__c = 90;
} else {
queryData.price__c = 2000;
queryData.discount__c = 80;
}
resolve(queryData);
})
}
}自定义字段
import Search from './search.vue'
export default class Plugin {
apply() {
return [{
event: 'form.render.before',
functional: this.formRenderBefore.bind(this)
}]
}
formRenderBefore(context, plugin) {
const { BaseComponents } = context;
return {
components: {
//name是字段的api_name,此处我们自定义的是主属性字段
name: BaseComponents.base.extend({
render() {
let me = this;
let vm = new Vue({
render: h => h(Search, {
on: {
//数据发生变更时
change(value) {
//setData有5个参数(value, apiname, noTrigger, isBlur, noCalculate)
//其中value为字段值,
//apiname为字段api_name,可以传空字符
//noTrigger不触发变更,默认传null
//isBlur是否手动修改它是触发字段UI函数的关键,传true
//noCalculate是否不触发计算,默认传空
me.setData(value, '', null, true);
}
}
})
}).$mount(this.$el[0]);
//此为固定写法,方便底层销毁组件
this.vmInstance = vm;
//this上还有一些实用的方法和属性可用
//this.disable()设置组件不可编辑
//this.enable()设置组件可编辑
//this.getData() 获取当前字段的初始值
//this.getData('xxxx')获取指定字段的值,xxxx为字段api_name
//this.show()显示组件
//this.hide()隐藏组件
//this.showTips('字段提示')给组件加提示
//this.hideTips()隐藏组件提示
//this.showError() 给组件加错误提示
//this.hideError() 隐藏错误提示
//this.isReadonly() 当前字段在布局中是否被设为只读
//this.isRequired() 当前字段在布局中是否被设为必填
//this.fieldAttr 当前字段的属性信息
},
//输出该字段的值
getValue(){
let value = this.getData();
// 这里只是简单演示必填验证,业务可以有自己的错误
if(this.isRequired() && !value) {
this.showError();
} else {
this.hideError();
}
return value;
},
//当外部修改字段值时会调用
setValue(val) {
//请确保你的vue组件上有setValue方法
this.vmInstance.setValue(val);
}
})
}
}
}
}注意:
自定义字段组件设置值请使用
setData,而不是使用context.dataUpdatergetValue和setValue方法需要实现,否则提交不了数据this.vmInstance = vm是一个固定写法
查找关联字段选数据时增加一些筛选条件
export default class Plugin {
apply() {
return [{
event: 'form.render.before',
functional: this.formRenderBefore.bind(this)
}]
}
formRenderBefore(context, plugin) {
return Promise.resolve({
fieldEditBeforeCallbacks: {
//account_id为字段api_name
account_id: [() => {
return Promise.resolve({
Value: {
beforeRequest(param) {
let sq = JSON.parse(param.search_query_info);
sq.filters.push({
field_name: 'name',
field_values: ['测试'],
operator: 'LIKE'
})
param.search_query_info = JSON.stringify(sq);
return param;
}
}
})
}]
}
})
}
}变更主对象默认值
export default class Plugin {
apply() {
return [
{
event: "form.render.before",
functional: this.formRenderBefore.bind(this)
}
];
}
formRenderBefore(plugin, context) {
context.dataUpdater.updateMaster({
name: "test"
});
}
}如何扩展分组
import Comp from './comp.vue'
export default class Plugin {
apply() {
return [
{
event: "form.render.before",
functional: this.formRenderBefore.bind(this)
}
];
}
formRenderBefore(context, plugin) {
return Promise.resolve({
groupSlots: [(item, el) => {
//base_field_section__c是分组的api_name
if(item.api_name === 'base_field_section__c') {
let vm = new Vue({
render: h => h(Comp, {
on: {
change() {
let newContext = plugin.api.pluginServiceFactory();
newContext.dataUpdater.updateMaster({field_mNzUn__c: '100'});
newContext.triggerCalAndUIEvent({changeFields: ['field_mNzUn__c']})
.then(rst => {
newContext.end(!!rst.StatusCode);
})
}
}
})
}).$mount()
$(el).append(vm.$el);
return {//必须返回
destroy() {
vm.$destroy();//销毁组件
}
}
}
}]
})
}
}拦截表单按钮,修改参数
export default class Plugin {
apply() {
return [
{
event: "form.render.before",
functional: this.formRenderBefore.bind(this)
}
];
}
formRenderBefore(context, plugin) {
return Promise.resolve({
beforeUIAction(param) {
//根据按钮的apiname 判断是需要处理的按钮
//此处演示当按钮点击时,给选中的数据增加一个标识__isPrint,方便函数识别
if(param.api_name === 'ceshi__c') {
//获取到从对象的数据 object_Wdf32__c 是从对象apiname
let details = param.details && param.details['object_Wdf32__c'];
if(details) {
let newContext = plugin.api.pluginServiceFactory();
//获取到选中的数据
let selectDatas = newContext.dataGetter.getCheckedDatas('object_Wdf32__c');
details.forEach(item => {
item.__isPrint = !!selectDatas.find((a) => a.rowId === item.rowId);
})
}
}
return Promise.resolve();
}
})
}
}在表单底部插入自己的业务组件
import Comp from './comp.vue'
export default class Plugin {
apply() {
return [
{
event: "form.render.before",
functional: this.formRenderBefore.bind(this)
}
];
}
formRenderBefore(context, plugin) {
return Promise.resolve({
footerSlot: [(el => {
let vm = new Vue({
render: h => h(Comp, {
on: {
change() {
let newContext = plugin.api.pluginServiceFactory();
newContext.dataUpdater.updateMaster({field_mNzUn__c: '100'});
newContext.triggerCalAndUIEvent({changeFields: ['field_mNzUn__c']})
.then(rst => {
newContext.end(!!rst.StatusCode);
})
}
}
})
}).$mount()
$(el).append(vm.$el);
return {//必须返回
destroy() {
vm.$destroy();//销毁组件
}
}
})]
})
}
}注意事项
1. dataUpdater使用可能不生效
由于从对象尚未初始化完成,与从对象相关的所有API都不生效。等待从对象初始化完成后,API将可正常使用。
附录
表单预设按钮
| 按钮 | action |
|---|---|
| 提交按钮 | submit |
| 提交并新建 | submitAndCreate |
| 保存草稿 | saveDraft |
| 取消 | cancel |
BaseComponents.base 原型属性和方法
| 方法 | 说明 | 类型 | 用法 |
|---|---|---|---|
| fieldAttr | 获取当前字段的字段描述数据 | 属性 | -- |
| getData | 获取字段的值 | 方法 | this.getData('field_a39cn__c') |
| setData | 设置字段的值第一个参数字段的值第二个参数,字段的apiname,传null第三个参数,此次修改是否不用触发变更,一般都是null第四个参数,表示此次修改是手动触发的,一般是true,用户底层触发UI函数第五个参数,是否不用触发计算,一般不用传 | 方法 | this.setData('ddd', 'field_a39cn__c') |
| isReadonly | 判断当前字段是否只读 | 方法 | this.isReadonly() |
| isRequired | 判断当前字段是否必填 | 方法 | this.isRequired() |
| showError | 展示错误信息 | 方法 | this.showError(null, '数据错误提示') |
| hideError | 隐藏错误信息 | 方法 | this.hideError() |
