As a developer, we need to know what tools we can use to achieve our task as efficient as possible. One of the API that now we want to learn is addOnSave. In short, addOnSave is an API that we can call to register an event to save the event to prevent or allow the changes.
For our demo purpose, I create a new entity called Custom Document which has 2 important fields called Type (OptionSet) and Description. So basically we want to validate if the Type selected is Case 1, we want to check Description contains the string “Case 1” or not. If match then we will allow saving, else prevent the save. All of the cases in this demo are the same. But in reality, you sure have different validation checking for each case.
var Blog = Blog || {};
Blog.Form = Blog.Form || {};
Blog.Business = Blog.Business || {};
var OPTIONS = {
'CASE_1': 772060000,
'CASE_2': 772060001,
'CASE_3': 772060002
};
(function() {
this.onSave_Validate1 = function(context) {
console.log('case 1');
var formContext = context.getFormContext();
var description = formContext.getAttribute('cr0c0_description')
.getValue() || '';
var valid = description.indexOf('Case 1') > -1;
if(valid) return;
context.getEventArgs().preventDefault();
};
this.onSave_Validate2 = function(context) {
console.log('case 2');
var formContext = context.getFormContext();
var description = formContext.getAttribute('cr0c0_description')
.getValue() || '';
var valid = description.indexOf('Case 2') > -1;
if(valid) return;
context.getEventArgs().preventDefault();
};
this.onSave_Validate3 = function(context) {
console.log('case 3');
var formContext = context.getFormContext();
var description = formContext.getAttribute('cr0c0_description')
.getValue() || '';
var valid = description.indexOf('Case 3') > -1;
if(valid) return;
context.getEventArgs().preventDefault();
};
this.registerType = function(context){
var formContext = context.getFormContext();
var type = formContext.getAttribute('cr0c0_type').getValue();
if(type === OPTIONS.CASE_1){
formContext.data.entity.addOnSave(Blog.Business.onSave_Validate1);
}else if(type === OPTIONS.CASE_2){
formContext.data.entity.addOnSave(Blog.Business.onSave_Validate2);
}else if(type === OPTIONS.CASE_3){
formContext.data.entity.addOnSave(Blog.Business.onSave_Validate3);
}
};
}).apply(Blog.Business);
(function() {
this.form_OnLoad = function(context) {
Blog.Business.registerType(context);
};
this.onType_Change = function(context) {
Blog.Business.registerType(context);
};
}).apply(Blog.Form);
Developer Notes
- To register event on save, we use formContext.data.entity.addOnSave(event).
- To prevent save, we use context.getEventArgs().preventDefault().
Here is the result:

If you check the log console. When the second time we click save on the form, you will see that the previous message (case 1) also prints again. It means that we registered both events (Event onSave_Validate3 and onSave_Validate2). If we keep changing the Type, our code will register the event based on how many times we change the Type. To avoid that, we need to do this:
var Blog = Blog || {};
Blog.Form = Blog.Form || {};
Blog.Business = Blog.Business || {};
var OPTIONS = {
'CASE_1': 772060000,
'CASE_2': 772060001,
'CASE_3': 772060002
};
var events = events || {};
(function() {
this.onSave_Validate1 = function(context) {
console.log('case 1');
var formContext = context.getFormContext();
var description = formContext.getAttribute('cr0c0_description')
.getValue() || '';
var valid = description.indexOf('Case 1') > -1;
if(valid) return;
context.getEventArgs().preventDefault();
};
this.onSave_Validate2 = function(context) {
console.log('case 2');
var formContext = context.getFormContext();
var description = formContext.getAttribute('cr0c0_description')
.getValue() || '';
var valid = description.indexOf('Case 2') > -1;
if(valid) return;
context.getEventArgs().preventDefault();
};
this.onSave_Validate3 = function(context) {
console.log('case 3');
var formContext = context.getFormContext();
var description = formContext.getAttribute('cr0c0_description')
.getValue() || '';
var valid = description.indexOf('Case 3') > -1;
if(valid) return;
context.getEventArgs().preventDefault();
};
var eventMappings = {
772060000: Blog.Business.onSave_Validate1,
772060001: Blog.Business.onSave_Validate2,
772060002: Blog.Business.onSave_Validate3
};
this.registerType = function(context){
var formContext = context.getFormContext();
var type = formContext.getAttribute('cr0c0_type').getValue();
if(!type) return;
for(var i in events){
var event = events[i];
formContext.data.entity.removeOnSave(event);
}
var selectedEvent = eventMappings[type];
if(!selectedEvent) return;
formContext.data.entity.addOnSave(selectedEvent);
events[type] = selectedEvent;
};
}).apply(Blog.Business);
(function() {
this.form_OnLoad = function(context) {
Blog.Business.registerType(context);
};
this.onType_Change = function(context) {
Blog.Business.registerType(context);
};
}).apply(Blog.Form);
The main changes in the code above are on the method registerType, we have obligation to call formContext.data.entity.removeOnSave(event) to remove unnecessary events. In the below picture, we can see case 3 and case 2 being called separately.

Awesome! keep up the good work
LikeLike