This is an article with a snippet of code demonstrating how to manage a subform using a Zoho CRM Client Script.
Why?
A client wanted an automation on-the-fly that when selecting a specific value in a field, a row would be added to a subform contained herein.
How?
Well I won't go in to detail on how to add a client script, this article is just to show the snippet of code used in the client script which will manage a subform.
The module we are applying this client script to is a custom module called "Deployments". The field which triggers it is called "Which_rate_card_is_this_based_off". The expected outcome is the appending of a row to the subform based on the start date (first field in the subform) match in which case it should re-add the row with an "End Date" specified (blank or not).
console.log("Joel Lipman - 20221018 -------------------------");
// get some values from the current record
var v_CurrencyCode = ZDK.Page.getField('Currency').getValue();
var v_ConsultantLocation = ZDK.Page.getField('Location').getValue();
// only run the rest if record matches criteria
if (v_CurrencyCode == "GBP" && v_ConsultantLocation == "UK") {
// get value of trigger field
var v_RateCard = ZDK.Page.getField('Which_rate_card_is_this_based_off').getValue();
// get opportunity lookup (related deal) of this record
let r_DealLookup = ZDK.Page.getField('Opportunity_Name').getValue();
let v_DealID = r_DealLookup.id;
let r_DealDetails = ZDK.Apps.CRM.Deals.fetchById(v_DealID);
// get Deal/Opportunity fields we need to refer to
var v_OppType = r_DealDetails.Type_of_Opportunity;
var v_DealRate0 = r_DealDetails.Rate_Year_1_0;
var v_DealRate1 = r_DealDetails.Rate_Year_1_5;
var v_DealRate2 = r_DealDetails.Rate_Year_2_0;
var v_DealRate3 = r_DealDetails.Rate_Year_3_0;
var v_DealRate4 = r_DealDetails.Rate_Year_4_0;
// default setting for alerting user
let b_ShowAlertMessage = true;
// specific values based on trigger field
if (v_RateCard == 'New Rate Card (Post Aug 22)' && (v_OppType == 'Client'||v_OppType == 'People') && v_CurrencyCode == 'GBP') {
// hard-coded values if this criteria met
v_DealRate0 = 350;
v_DealRate1 = 390;
v_DealRate2 = 465;
v_DealRate3 = 535;
v_DealRate4 = 590;
b_ShowAlertMessage = false;
} else if (v_RateCard == 'Old Rate Card (Pre Aug 22)' && (v_OppType == 'Client'||v_OppType == 'People') && v_CurrencyCode == 'GBP') {
// hard-coded values if this criteria met
v_DealRate0 = 345;
v_DealRate1 = 345;
v_DealRate2 = 400;
v_DealRate3 = 475;
v_DealRate4 = 525;
b_ShowAlertMessage = false;
}
// show advisory
if (b_ShowAlertMessage) {
ZDK.Client.showAlert("You have selected a rate without any preset values. Rates will be taken from the Opportunity record. If these are blank then enter the rates manually below: Rate Year 1.0, Rate Year 1.5, ...");
}
// update the fields (that were blank on the existing record - but now pulled from Opp or from set values)
ZDK.Page.getForm().setValues({ 'Rate_Year_1_0': v_DealRate0 });
ZDK.Page.getForm().setValues({ 'Rate_Year_1_5': v_DealRate1 });
ZDK.Page.getForm().setValues({ 'Rate_Year_2_0': v_DealRate2 });
ZDK.Page.getForm().setValues({ 'Rate_Year_3_0': v_DealRate3 });
ZDK.Page.getForm().setValues({ 'Rate_Year_4_0': v_DealRate4 });
// start subform management
// *****************************************
// declare the new row and JSON argument
var json_Row = new Array();
var json_Arg = new Object();
// get some values beforehand which allows us to compare to the rows already present in the subform
// first column to add in this row is start date (retrieved from field "Actual Start Date" on this record)
var v_StartDateValue = ZDK.Page.getField('Actual_Start_Date').getValue();
var v_LocalStartDate = new Date(v_StartDateValue);
// accommodate for timezone offset
v_LocalStartDate.setMinutes(v_LocalStartDate.getMinutes() - v_LocalStartDate.getTimezoneOffset());
// return in yyyy-mm-dd format (on save this will display as per the format on the CRM record)
v_StartDateFormatted = v_LocalStartDate.toJSON().slice(0, 10);
// add this as one argument in the JSON
json_Arg.Start_Date = v_StartDateFormatted;
// check if end date is specified and if it is then add to this row
v_EndDate = null;
v_EndDateValue = ZDK.Page.getField('Actual_Finish_Date').getValue();
if (v_EndDateValue !== null) {
var v_LocalEndDate = new Date(v_EndDateValue);
v_LocalEndDate.setMinutes(v_LocalEndDate.getMinutes() - v_LocalEndDate.getTimezoneOffset());
v_EndDateFormatted = v_LocalEndDate.toJSON().slice(0, 10);
json_Arg.End_Date = v_EndDateFormatted;
}
// add currency code into column "Agreed Currency"
json_Arg.Agreed_Currency = v_CurrencyCode;
// the rate values we determine earlier
json_Arg.Rate_Year_1_0 = v_DealRate0;
json_Arg.Rate_Year_1_5 = v_DealRate1;
json_Arg.Rate_Year_2_0 = v_DealRate2;
json_Arg.Rate_Year_3_0 = v_DealRate3;
json_Arg.Rate_Year_4_0 = v_DealRate4;
// get current user to put as the new row owner (other possible values: id, full_name, email)
v_CrmUser_FullName = $Crm.user.full_name;
json_Arg.Rate_Change_Owner = v_CrmUser_FullName;
// other fields to fill in for this subform row
v_RateCardDisp = v_RateCard.indexOf(" (")>0 ? v_RateCard.substring(0, v_RateCard.indexOf(" (")) : v_RateCard;
json_Arg.Rate_Change_Notes = v_RateCardDisp;
// get existing subform with only the displayed rows (not been deleted)
var l_existingSubformRows = ZDK.Page.getField('Deployment_Rate_Log').getValue();
// loop through to exclude any rows we don't want based on criteria
l_NewSubformRows = new Array();
for (i = 0; i < l_existingSubformRows.length; i++) {
// check row hasn't already been entered, here we are using the start date to determine if this has already been entered
v_CheckField1 = l_existingSubformRows[i].Start_Date;
var v_LocalCheckDate = new Date(v_CheckField1);
v_LocalCheckDate.setMinutes(v_LocalCheckDate.getMinutes() - v_LocalCheckDate.getTimezoneOffset());
v_CheckField1Formatted = v_LocalCheckDate.toJSON().slice(0, 10);
// if the new row to add matches an existing one but ignoring the end date, then it will omit this to re-add it with an end date.
if (v_CheckField1Formatted != v_StartDateFormatted) {
l_NewSubformRows.push(l_existingSubformRows[i]);
}
}
json_Row = l_NewSubformRows;
// put the arguments into a single row (json array)
json_Row.push(json_Arg);
// need to stringify AND parse otherwise this won't work
var json_Parsed = JSON.parse(JSON.stringify(json_Row));
// set new subform rows
ZDK.Page.getField('Deployment_Rate_Log').setValue(json_Parsed);
}
// don't save record?
return false;
Note(s)
-
Using the following line returns all subform rows, even deleted ones, which is why we didn't use this command in the system. But keeping it for future reference.
var l_existingSubformRows = ZDK.Apps.CRM.Deployment_Rate_Log.fetch();
Another example of looping through a subform
In the following snippet of code, we are going to loop through a subform called "Skillset" which has a column called "Skill" which is a lookup to the "Skills" module. This client script is triggered when the user hits the "Save" button (event: onSave) and will stop the user from saving the record and continuing if 3 different skills are not specified in the subform:
// initialize
var v_CalculatedNumberOfSkills = 0;
// get the Opp stage
var v_OppStage = ZDK.Page.getField('Stage').getValue();
// get the Skills subform
var l_SkillsSubform = ZDK.Page.getField('Skillset').getValue();
var l_AlreadyListed = Array();
// loop through subform rows and check if column "Skill" has unique values
for (var i = 0; i < l_SkillsSubform.length; i++) {
// convert this row to an object
o_SkillName = JSON.parse(JSON.stringify(l_SkillsSubform[i]));
// check the skill is not blank
if (o_SkillName.Skill != null) {
// parse out the name (Skill is a lookup field)
v_SkillName = o_SkillName.Skill.name;
// check if skill is not null and has not already been listed
if (v_SkillName != null && l_AlreadyListed.indexOf(v_SkillName) < 0) {
// increment
v_CalculatedNumberOfSkills += 1;
// add to list of used values
l_AlreadyListed.push(v_SkillName);
}
}
}
// set the value of No_Skills_Listed field
ZDK.Page.getForm().setValues({ 'No_Skills_Listed': v_CalculatedNumberOfSkills });
// if not 3 or greater then alert the user and prevent the save
if (v_CalculatedNumberOfSkills < 3 && v_OppStage == "Qualified") {
ZDK.Client.showAlert("Please list at least 3 different skills relevant to the opportunity in the 'Skills' section before progressing.");
// prevent save of the record
return false;
}
Source(s):
Discussion
Comments
Questions, corrections and useful additions are reviewed before appearing here.
No comments yet. Start the discussion.