# Create a JS plug-in for the edit page

The New Edit Page JS plugin contains the following extension scenarios:

  • Modify the Field component
  • Control the form flow
  • Interception of business actions

# Modify the Field component

Example: Disable a field

export default {
   // 字段判断
   entry(context, field) {
       return field.api_name == 'field_gq0EF__c'
   },
   // 渲染
   render(context, field, value) {
       return '<span>该字段不允许填写内容!!</span>';
   }
}



# Control the form flow

Example: Suppose we store special data (serialized by JSON) with multiple lines of text, and the form needs to be JSON parsed when rendering, and then backfilled on other fields.

export default {
   // 渲染之前
   beforeRender(context) {
       const value = context.getData('field_18288__c');
       let data = null;
       if (value) {
           data = JSON.parse(value);
       }
       if (data) {
           context.setData('field_gq0EF__c', data.test);
       }
       return Promise.resolve();
   }
}



# Intercept business information

Example 1: Intercept the click event of the associated field object selection button and execute the customized object selection logic.

export default {
   // 绑定点击事件
   registerListener() {
       this.addFieldClickListeners('field_hlqjV__c.selectObj');
   },
   // 点击处理
   click(context, e) {
       if (e.eventTarget === 'selectObj') {
           FxUI.objectUIAction.selectObject('AccountObj', {
               // ... 选对象参数,见API章节
           }).then({
               objectList
           } => {
               context.setData('field_hlqjV__c', objectList[0]._id);
               context.setData('field_hlqjV__c__r', objectList[0].name);
           });
       }
   }
}



Example 2: Intercept the click event of the delete button from the object data and decide whether to allow deletion based on the field value.

export default {
   //绑定点击事件
   registerListener() {
       this.addMdClickListeners('object_R9tuj__c.delRow');
   },
   //点击处理
   click(context, e, next) {
       if (e.cellData.name !== '不允许删除') {
           next();
       }
   }
}



# Modify the Field component

This type of requirement needs to be implemented through the following APIs:

# entry()

Parameter:

  • context: Object : The context of the field
  • field: Object : Field description information

Usage:

This hook defines which fields need to be re-rendered by the plugin. You can judge by the api_name of the field and the field type.

Example:

// 通过字段api_name判断
export default {
   entry(context, field) {
       return field.api_name === 'field_bbbb__c';
   }
}
// 通过字段类型判断
export default {
   entry(context, field) {
       return field.type === 'text';
   }
}



# render()

Parameter:

  • context: Object : The context of the field
  • field: Object : Field description information
  • value: * : The value of the field
  • wrapper: Object : The rendered container DOM

Return:

You can return the rendered DOM string or DOM object, or you may not return it.

Usage:

View rendering functions

Example:

// 返回dom字符串
export default {
   render(context, field, value) {
       return '<span>hello fxiaoke</span>'
   }
}
// 返回dom对象
export default {
   render(context, field, value) {
       var vm = new Vue({
           render: h => h('div', 'hello fxiaoke')
       }).$mount();
       return vm.$el;
   }
}
// 不返回结果
export default {
   render(context, field, value, wrapper) {
       var vm = new Vue({
           render: h => h('div', 'hello fxiaoke')
       }).$mount();
       wrapper.appendChild(vm.$el);
   }
}



# Complete example

export default {
   entry(context, field) {
       return field.api_name === 'field_aaaa__c' || field.api_name === 'field_bbbb__c';
   },
   render(context, field, value, wrapper) {
       if(field.api_name === 'field_aaaa__c') {
           return `
               <input type="text" value="${value}" />
           `
       }else if(field.api_name === 'field_bbbb__c') {
           const ipt = document.createElement('input');
           ipt.value = value;
           ipt.setAttribute('type', 'text');
           wrapper.appendChild(ipt);
       }
   }
}



# Control the form flow

This type of requirement needs to be implemented through the following APIs:

# beforeParse()

Parameter:

  • context: Object : The context of the field
  • data: Object : The data returned by the form interface, including information such as form layout and form backfill data

Return:

  • promise: Promise The value of :p ROMISE is the processed data.

Usage:

beforeParse occurs after the interface is successfully invoked, before the response data is parsed.

export default {
   ...
   beforeParse(context, data) {
       output('beforeParse', arguments);
       return new Promise(resolve => {
           data.objectData.name = '新值';
           resolve(data)
       });
   },
   ...
}



# beforeRender()

Parameter:

  • context: Object : The context of the field

Return:

  • promise: Promise : No need to pass data.

Usage:

beforeRender occurs after the data is parsed and before the view is rendered.

export default {
   ...
   beforeRender() {
       output('beforeRender', arguments);
       return new Promise(resolve => {
           resolve()
       });
   },
   ...
}



# rendered()

Parameter:

  • context: Object : The context of the field

Return:

  • promise: Promise : No need to pass data.

Usage:

Rendered occurs after the view is rendered.

export default {
   ...
   rendered() {
       output('rendered', arguments);
       return new Promise(resolve => {
           resolve()
       });
   },
   ...
}



# beforeSubmit()

Parameter:

  • context: Object : The context of the field
  • postData: Object : The data that needs to be submitted when the form is saved

Return:

  • promise: Promise The value of :p ROMISE is the processed data.

Usage:

beforeSubmit occurs before the data is saved.

export default {
   ...
   beforeSubmit: function(context, postData) {
       output('beforeSubmit', arguments);
       return new Promise(resolve => {
           resolve(postData)
       });
   },
   ...
}



# submited()

Parameter:

  • context: Object : The context of the field
  • res: Object : The data returned after the form data is saved

Return:

  • promise: Promise The value of :p ROMISE is the processed data.

Usage:

Submitted occurs after the data is saved.

export default {
   ...
   submited: function(context, res) {
       output('submited', arguments);
       return new Promise(resolve => {
           resolve(res)
       });
   },
   ...
}



# validated(context, result)

Parameter:

  • context: Object : The context of the field
  • result: Boolean : Whether the verification passed

Return:

  • isPass: Boolean : Whether the verification passed

Usage:

Validated happens after the built-in validation logic.

export default {
   ...
   validated() {
       output('beforeRender', arguments);
       return true;
   },
   ...
}



# getTitle(context, data)

Parameter:

  • context: Object : The context of the field
  • data: Object :data
    • data.isEdit: Boolean : Whether it is an edit or not

Return:

  • title: String : The title of the form component.

Usage:

export default {
   ...
   getTitle() {
       output('beforeRender', arguments);
       return '新标题';
   },
   ...
}



# getMdColumnRenders(context, data)

Return:

  • rules: Object : From Object Layout Rule

Usage:

The returned data is relatively complex.

export default {
   ...
   getMdColumnRenders() {
       return {
           object_adlkjd__c: {
               field_dlkjdd__c: {
                   depend_fields: ['field_aaaaa__c', 'field_bbbbb__c'],
                   render(val, data) {
                       return '<div>...</div>'
                   }
               }
           }
       }
   },
   ...
}



# Intercept business behavior

# registerListener()

Usage:

This method needs to be rewritten after the form is rendered.

export default {
   registerListener() {
       this.addFieldClickListeners('name');
   }
}



# addFormClickListeners()

Parameter:

  • eventName: String : Button apiName

Usage:

export default {
   registerListener() {
       this.addFormClickListeners('button_ccccc__c');
   }
}



# addFieldClickListeners()

Parameter:

  • eventName: String : Event name, in the format: fieldApiName.[btnName]
    • options: Object : Other parameters
    • options.selector: String : Element selector

Usage:

Bind the click event on the field.

export default {
   registerListener() {
       this.addFieldClickListeners('field_ax3c__c.btnName');
       this.addFieldClickListeners('field_ax3c__c', {
           selector: '.btn'
       });
   }
}



Preset btnName:

  1. selectObj: Find the selection button for the associated field
export default {
   registerListener() {
       this.addFieldClickListeners('lookup_field__c.selectObj');
   }
}



# addMdClickListeners()

Parameter:

  • eventName: String : Event name, in the format: detailObjectApiName.[btnName]

Usage:

Bind the click event from the object.

export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.delRow');
       this.addMdClickListeners('object_bW95o__c.singleAdd');
   }
}



Preset btnName:

  1. delRow: Deletes the click event from the Object Data button
export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.delRow');
   }
}



  1. singleAdd: Add a click event from the Object Data (Single) button
export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.singleAdd');
   }
}



  1. batchAdd: Add click events from object data buttons (multiple bars) buttons
export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.batchAdd');
   }
}



  1. batchAddConfirm: Bulk add click events from object data when selecting data to determine buttons
export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.batchAddConfirm');
   }
}



  1. copyRow: Copies the click event from the object data button
export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.copyRow');
   }
}



  1. rowCell: Click events for read-only fields
export default {
   registerListener() {
       this.addMdClickListeners('object_bW95o__c.rowCell');
   }
}



# click()

Parameter:

  1. A handler for binding a form button click event
  • context: Object : The context of the field
  • e: Object : Event object
  • eventTarget: String : button apiName
  • eventName: String : Fixed value - click
  • type: String : Fixed value - form
  • _originEvent : The original event object
  • next: Function : The callback function, which continues the original logic, needs to be called manually
  1. A handler for binding field click events
  • context: Object : The context of the field
  • e: Object : Event object
    • fieldApiName: String : field apiName
    • fieldValue: * : The value of the field
    • eventName: String : Fixed value - click
    • type: String : Fixed value - field
    • _originEvent : The original event object
    • next: Function : The callback function, which continues the original logic, needs to be called manually
  1. A handler that binds the click event from the object form
  • context: Object : The context of the field
  • e: Object : Event object
    • cellData: Object : Current data
    • objectApiName: String : From object apiName
    • eventTarget: String : The business action performed by the button
    • eventName: String : Fixed value - click
    • type: String : Fixed value - md
    • next: Function : The callback function, which continues the original logic, needs to be called manually

Usage:

This method is called when a click is triggered and needs to be overridden.

export default {

   registerListener() {
       this.addFieldClickListeners('field_xxxx__c.btnName');
       this.addFieldClickListeners('field_yyyy__c', {
           selector: '.btn'
       });

       this.addMdClickListeners('object_bW95o__c.delRow');
       this.addMdClickListeners('object_bW95o__c.singleAdd');
   },

   click(context, e, next) {
       console.log(context);
       console.log(e);
       next(); //该方法可以用来阻塞原有的业务逻辑
   }

}



# addFieldChangeListeners()

Parameter:

  • eventName: String : Event name, in the format: . fieldApiName
  • options: Object : Other parameters
    • options.selector: String : Element selector

Custom fields, you must pass selector to listen to the change event; The pre-made field will listen to the change event of the original input element by default.

Usage:

Bind the change event of the form on the field

export default {
   registerListener() {
       this.addFieldChangeListeners('field_xxxx__c');
       this.addFieldChangeListeners('field_yyyy__c', {
           selector: '.btn'
       });
   }
}



# addFieldValueChangeListeners(eventName)

Parameter:

  • eventName: String :Event name, format: fieldApiName

Usage:

The value on the listening field changes.

export default {
   registerListener() {
       this.addFieldValueChangeListeners('owner');
   }
}



Example:

If we want to bring the owner information to the main attribute (name), we need to monitor the change of the owner's value to modify the value of the main attribute in real time.

export default {
   //绑定点击事件
   registerListener() {
       this.addFieldValueChangeListeners('owner');
   },
   //点击处理
   change(context, e, next) {
       console.log(arguments);
   	if (e.fieldApiName === 'owner' || e.type === 'data') {
   		let nameValue = context.getData('name').name;
   		if (nameValue){
   			const ownerValue = e.value;
               const employee = FxUI.organization.getEmployeeById(ownerValue[0]);
               nameValue = nameValue.replace(/-(.*?)$/, '') + '-' + employee.name;
               context.setData('name', nameValue);
   		}
   	}
   }
}



# change()

parameter:

  • context: Object :Context of the field
  • e: Object: event object
    • fieldApiName: String: field apiName
    • fieldValue: *: field value
    • eventName: String: fixed value change
    • type: String: fixed values field and data
    • _originEvent: original event object

Usage:

This method will be called when the form input box is out of focus, and you need to rewrite it.

export default {

   registerListener() {
       this.addFieldChangeListeners('field_xxxx__c');
       this.addFieldChangeListeners('field_yyyy__c', {
           selector: '.ipt'
       });
   },

   change(context, e) {
       console.log(context);
       console.log(e);
   }

}



# addFieldInputListeners()

parameter:

  • eventName: String :Event name, format: fieldApiName
  • options: Object :Other parameters
    • options.selector: String :Element Selector

If there is no selector, the input element in the field will be bound by default.

Usage:

The input event of the form on the bound field

export default {
   registerListener() {
       this.addFieldInputListeners('field_ax3c__c');
       this.addFieldInputListeners('field_ax3c__c', {
           selector: '.btn'
       });
   }
}



# input()

parameter:

  • context: Object :Context of the field
  • e: Object : Event object
    • fieldApiName: String : field apiName
    • fieldValue: * : The value of the field
    • eventName: String : Fixed value input
    • type: String : Fixed value field
    • _originEvent : The original event object

Usage:

This method will be called when the form input box is triggered to input characters, and you need to rewrite it.

export default {

   registerListener() {
       this.addFieldInputListeners('field_xxxx__c');
       this.addFieldInputListeners('field_yyyy__c', {
           selector: '.ipt'
       });
   },

   input(context, e) {
       console.log(context);
       console.log(e);
   }

}



# Complete example

export default {
   registerListener() {
       this.addFieldClickListeners('field_0zc2Z__c.selectObj');
       this.addFieldChangeListeners('field_5X90M__c');
       this.addFieldInputListeners('field_5X90M__c');

       // only - class
       this.addFieldChangeListeners('field_1G017__c', {
           selector: '.ipt'
       });
       this.addFieldClickListeners('field_1G017__c');
   },

   click(context, e) {
       console.log(context);
       console.log(e);
   },

   change(context, e) {
       console.log(context);
       console.log(e);
   },

   input(context, e) {
       console.log(context);
       console.log(e);
   }
}




# context

# getDescribe()

Return:

  • describe: Object : The description of the object
    • api_name: String : The apiName of the object
    • display_name: String : The name of the object
    • fields: Object : All fields of the object

Usage:

The method returns object description information for the current object.

const describe = context.getDescribe();
console.log(describe.api_name);
console.log(describe.fields);



# getFields()

Usage:

Returns all fields under the object.

const fields = context.getFields();
console.log(fields.name);
console.log(fields.owner);



# getDetailDescribeByApiName()

Parameter:

  • detail_api_name: String : apiName from the object

Usage:

The method returns object description information from the object.

const describe = context.getDetailDescribeByApiName('detail_api_name');
console.log(describe.api_name);
console.log(describe.fields);



# getAllDetailDescribes()

Usage:

The method returns all the object description information from the object.

const describes = context.getAllDetailDescribes();
describes.forEach(describe => {
   console.log(describe);
})



# getData()

Parameter:

  • fieldApiName: String : apiName of the field (optional)

Usage:

The method returns the data for the main object.

const data = context.getData();
console.log(data.name);
console.log(data.owner);

const nameValue = context.getData('name');
console.log(nameValue);



# setData()

parameter:

  • fieldApiName: String | Object :字段的apiName
  • value: * :The value of the field

Usage:

Set data.

context.setData('name', 'fxiaoke');
context.setData({
   'name': 'fxiaoke',
   'owner': [1000]
});



# getDetailDataByApiName()

Parameter:

  • apiName: String : The apiName of the object
  • recordType: String : The business type of the object (optional)

Return:

Data from the object under fixed apiName (fixed business type).

Usage:

Gets data from an object of a business type

let data = context.getDetailDataByApiName('object_ad3xs__c');
let data1 = context.getDetailDataByApiName('object_ad3xs__c', 'default__c');



# getAllDetailDatas()

Return:

Get all the data from the object.

Usage:

const data = context.getAllDetailDatas();
console.log(data);



# updateDetailDataByApiName(apiName, list)

Parameter:

  • apiName: String : The apiName of the object
  • list: Array : All the data of the object, record_type in the data is required

Usage:

Updating all data from an object, deleting, adding, or updating can be done without triggering calculations and UI events

context.updateDetailDataByApiName(apiName, [{}]);





lastUpdate: 11/14/2022, 3:38:09 PM