Form-Level JavaScript Actions for Account Form in MS Dynamics CRM v9.2 (Samples)
1. Checking Form Type
The form type indicates whether the form is in create, update, read-only, or another mode.
function checkFormType(executionContext) {
var formContext = executionContext.getFormContext();
var formType = formContext.ui.getFormType(); // Get the form type
// Form types: 1 = Create, 2 = Update, 3 = Read Only, 4 = Disabled, 6 = Bulk Edit
switch (formType) {
case 1:
console.log("This is a Create form");
break;
case 2:
console.log("This is an Update form");
break;
case 3:
console.log("This is a Read-Only form");
break;
default:
console.log("Other form type: " + formType);
}
}
2. Checking Form State (Dirty Check)
Check if the form has unsaved changes (i.e., is "dirty").
function checkFormState(executionContext) {
var formContext = executionContext.getFormContext();
// Check if the form has unsaved changes
if (formContext.data.entity.getIsDirty()) {
console.log("Form has unsaved changes!");
} else {
console.log("Form is clean (no unsaved changes).");
}
}
3. Getting and Setting Field Data
Below are examples for getting and setting values for different field types on the Account form.
a. Single Line of Text (e.g., "name")
function handleTextField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the value of the Account Name field
var accountName = formContext.getAttribute("name").getValue();
console.log("Account Name: " + accountName);
// Set a new value for the Account Name field
formContext.getAttribute("name").setValue("New Account Name");
}
b. Option Set (e.g., "accountcategorycode")
function handleOptionSet(executionContext) {
var formContext = executionContext.getFormContext();
// Get the selected value of the Category field (returns integer)
var category = formContext.getAttribute("accountcategorycode").getValue();
console.log("Category Value: " + category); // e.g., 1 = Preferred Customer
// Set a new value (use a valid option set value)
formContext.getAttribute("accountcategorycode").setValue(2); // 2 = Standard
}
c. Lookup Field (e.g., "primarycontactid")
function handleLookupField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the value of the Primary Contact lookup
var primaryContact = formContext.getAttribute("primarycontactid").getValue();
if (primaryContact) {
console.log("Primary Contact ID: " + primaryContact[0].id);
console.log("Primary Contact Name: " + primaryContact[0].name);
}
// Set a new value for the Primary Contact lookup
var lookupValue = [{
id: "{GUID-OF-CONTACT}", // Replace with a valid Contact GUID
entityType: "contact",
name: "John Doe"
}];
formContext.getAttribute("primarycontactid").setValue(lookupValue);
}
d. Date Field (e.g., "createdon")
function handleDateField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Created On date value
var createdOn = formContext.getAttribute("createdon").getValue();
console.log("Created On: " + createdOn);
// Set a new date value (e.g., today's date)
var today = new Date();
formContext.getAttribute("createdon").setValue(today);
}
e. Currency Field (e.g., "revenue")
function handleCurrencyField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Annual Revenue value
var revenue = formContext.getAttribute("revenue").getValue();
console.log("Annual Revenue: " + revenue);
// Set a new value for Annual Revenue
formContext.getAttribute("revenue").setValue(50000.00); // Set to 50,000
}
f. Two Options (Boolean) (e.g., "donotemail")
function handleBooleanField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Do Not Email value (true/false)
var doNotEmail = formContext.getAttribute("donotemail").getValue();
console.log("Do Not Email: " + doNotEmail);
// Set a new value (true = Yes, false = No)
formContext.getAttribute("donotemail").setValue(true); // Set to Yes
}
g. Multi-Select Option Set (e.g., custom field "new_multiselect")
function handleMultiSelect(executionContext) {
var formContext = executionContext.getFormContext();
// Get the selected values of a multi-select option set
var multiSelect = formContext.getAttribute("new_multiselect").getValue();
console.log("Selected Values: " + multiSelect); // Returns array of integers
// Set new values (array of valid option set values)
formContext.getAttribute("new_multiselect").setValue([100000001, 100000002]);
}
4. Showing/Hiding Fields
Control the visibility of fields based on conditions.
function toggleFieldVisibility(executionContext) {
var formContext = executionContext.getFormContext();
// Check if Account Name is populated
if (formContext.getAttribute("name").getValue()) {
formContext.getControl("telephone1").setVisible(true); // Show Telephone
} else {
formContext.getControl("telephone1").setVisible(false); // Hide Telephone
}
}
5. Enabling/Disabling Fields
Make fields editable or read-only dynamically.
function toggleFieldEnabled(executionContext) {
var formContext = executionContext.getFormContext();
// Disable the Telephone field if Revenue is less than 10000
var revenue = formContext.getAttribute("revenue").getValue();
if (revenue < 10000) {
formContext.getControl("telephone1").setDisabled(true); // Disable field
} else {
formContext.getControl("telephone1").setDisabled(false); // Enable field
}
}
6. Setting Field Requirement Level
Dynamically set a field as required, recommended, or optional.
function setFieldRequirement(executionContext) {
var formContext = executionContext.getFormContext();
// Set Telephone as required if Category is "Preferred Customer" (value = 1)
var category = formContext.getAttribute("accountcategorycode").getValue();
if (category === 1) {
formContext.getAttribute("telephone1").setRequiredLevel("required");
} else {
formContext.getAttribute("telephone1").setRequiredLevel("none");
}
}
7. Refreshing the Form
Refresh the form data without reloading the entire page.
function refreshForm(executionContext) {
var formContext = executionContext.getFormContext();
// Refresh form data from the server
formContext.data.refresh(true).then(
function() { console.log("Form refreshed successfully"); },
function(error) { console.log("Error refreshing form: " + error.message); }
);
}
8. Saving the Form
Force the form to save programmatically.
function saveForm(executionContext) {
var formContext = executionContext.getFormContext();
// Save the form
formContext.data.save().then(
function() { console.log("Form saved successfully"); },
function(error) { console.log("Error saving form: " + error.message); }
);
}
9. Switching Forms
Navigate to a different form based on a condition (assuming multiple forms exist for the Account entity).
function switchForm(executionContext) {
var formContext = executionContext.getFormContext();
// Get available forms
var forms = formContext.ui.formSelector.items.get();
// Switch to a specific form (e.g., "Information" form) if condition met
var revenue = formContext.getAttribute("revenue").getValue();
if (revenue > 100000) {
for (var i in forms) {
if (forms[i].getLabel() === "Information") {
forms[i].navigate(); // Switch to the "Information" form
break;
}
}
}
}
10. Adding Form Notifications
Display a notification on the form.
function addNotification(executionContext) {
var formContext = executionContext.getFormContext();
// Add a warning notification if Revenue is null
if (!formContext.getAttribute("revenue").getValue()) {
formContext.ui.setFormNotification(
"Please enter the Annual Revenue.", // Message
"WARNING", // Level: INFO, WARNING, ERROR
"revenueNotification" // Unique ID for the notification
);
} else {
formContext.ui.clearFormNotification("revenueNotification"); // Clear notification
}
}
More:
1. Show/Hide a Section
Show or hide a section (e.g., "General" section) based on a condition.
function toggleSectionVisibility(executionContext) {
var formContext = executionContext.getFormContext();
// Get the section by its name (e.g., "General" section in a tab)
var section = formContext.ui.tabs.get("tab_general").sections.get("section_general");
// Show section if Revenue > 10000, hide otherwise
var revenue = formContext.getAttribute("revenue").getValue();
if (revenue > 10000) {
section.setVisible(true); // Show the section
} else {
section.setVisible(false); // Hide the section
}
}
2. Show/Hide a Tab
Show or hide an entire tab (e.g., "Details" tab) based on a condition.
function toggleTabVisibility(executionContext) {
var formContext = executionContext.getFormContext();
// Get the tab by its name (e.g., "tab_details")
var tab = formContext.ui.tabs.get("tab_details");
// Show tab if Category is "Preferred Customer" (value = 1), hide otherwise
var category = formContext.getAttribute("accountcategorycode").getValue();
if (category === 1) {
tab.setVisible(true); // Show the tab
} else {
tab.setVisible(false); // Hide the tab
}
}
3. Expand/Collapse a Tab
Expand or collapse a tab programmatically.
function toggleTabExpansion(executionContext) {
var formContext = executionContext.getFormContext();
// Get the tab by its name (e.g., "tab_summary")
var tab = formContext.ui.tabs.get("tab_summary");
// Expand tab if form is in Create mode (formType = 1)
if (formContext.ui.getFormType() === 1) {
tab.setDisplayState("expanded"); // Expand the tab
} else {
tab.setDisplayState("collapsed"); // Collapse the tab
}
}
4. Lock/Unlock All Fields in a Section
Enable or disable all fields within a specific section.
function lockSectionFields(executionContext) {
var formContext = executionContext.getFormContext();
// Get the section (e.g., "section_contact_info" in "tab_general")
var section = formContext.ui.tabs.get("tab_general").sections.get("section_contact_info");
// Iterate through all controls in the section
section.controls.forEach(function(control) {
// Disable fields if Account Name is not set
if (!formContext.getAttribute("name").getValue()) {
control.setDisabled(true); // Disable the control
} else {
control.setDisabled(false); // Enable the control
}
});
}
5. Dynamically Populate Option Set Values
Add or remove options in an option set dynamically.
function populateOptionSet(executionContext) {
var formContext = executionContext.getFormContext();
// Get the option set control (e.g., "industrycode")
var optionSetControl = formContext.getControl("industrycode");
// Clear existing options
optionSetControl.clearOptions();
// Add custom options dynamically
optionSetControl.addOption({ text: "Technology", value: 1 });
optionSetControl.addOption({ text: "Finance", value: 2 });
optionSetControl.addOption({ text: "Healthcare", value: 3 });
}
6. Retrieve Related Record Data (e.g., Primary Contact)
Use Web API to fetch data from a related record.
function fetchRelatedContact(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Primary Contact lookup value
var primaryContact = formContext.getAttribute("primarycontactid").getValue();
if (primaryContact) {
var contactId = primaryContact[0].id.replace("{", "").replace("}", "");
// Use Web API to retrieve contact's email
Xrm.WebApi.retrieveRecord("contact", contactId, "?$select=emailaddress1").then(
function(result) {
console.log("Contact Email: " + result.emailaddress1);
// Optionally set a field with the retrieved value
formContext.getAttribute("emailaddress1").setValue(result.emailaddress1);
},
function(error) {
console.log("Error fetching contact: " + error.message);
}
);
}
}
7. Prevent Form Save
Block form save if a condition is not met.
function preventSave(executionContext) {
var formContext = executionContext.getFormContext();
// Prevent save if Telephone is empty
if (!formContext.getAttribute("telephone1").getValue()) {
executionContext.getEventArgs().preventDefault(); // Block the save
formContext.ui.setFormNotification(
"Telephone is required before saving.",
"ERROR",
"telephoneError"
);
} else {
formContext.ui.clearFormNotification("telephoneError");
}
}
8. Filter Lookup Field Options
Apply a custom filter to a lookup field (e.g., filter Primary Contact by Account).
function filterLookup(executionContext) {
var formContext = executionContext.getFormContext();
// Define a fetchXML filter to show only contacts related to this account
var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
var fetchXml = "";
// Apply the filter to the Primary Contact lookup
formContext.getControl("primarycontactid").addCustomFilter(fetchXml, "contact");
}
9. Calculate Field Value (e.g., Total Revenue)
Calculate a value based on other fields and update a field.
function calculateTotalRevenue(executionContext) {
var formContext = executionContext.getFormContext();
// Get values from fields (e.g., revenue and a custom field "new_additionalrevenue")
var revenue = formContext.getAttribute("revenue").getValue() || 0;
var additionalRevenue = formContext.getAttribute("new_additionalrevenue").getValue() || 0;
// Calculate total
var totalRevenue = revenue + additionalRevenue;
// Set the total to a custom field (e.g., "new_totalrevenue")
formContext.getAttribute("new_totalrevenue").setValue(totalRevenue);
}
10. Open a Custom HTML Dialog
Display a custom dialog box with HTML content.
function openCustomDialog(executionContext) {
var formContext = executionContext.getFormContext();
// Define custom HTML content
var dialogContent = "
Account Details
Name: " + formContext.getAttribute("name").getValue() + "
Revenue: " + formContext.getAttribute("revenue").getValue() + "
";
// Define dialog options
var dialogOptions = {
height: 300,
width: 400
};
// Open the dialog
Xrm.Navigation.openAlertDialog({ text: dialogContent, confirmButtonLabel: "OK" }, dialogOptions);
}
Advanced:
1. Refresh a Subgrid
Refresh a subgrid (e.g., Contacts subgrid) to reflect updated data.
function refreshSubgrid(executionContext) {
var formContext = executionContext.getFormContext();
// Get the subgrid control (e.g., "Contacts" subgrid)
var subgrid = formContext.getControl("Contacts");
if (subgrid) {
// Refresh the subgrid
subgrid.refresh();
console.log("Contacts subgrid refreshed.");
} else {
console.log("Subgrid not found or not loaded yet.");
}
}
2. Add a Custom Button to a Subgrid
Add a custom button to a subgrid’s command bar (requires ribbon customization).
function addCustomSubgridButton(executionContext) {
var formContext = executionContext.getFormContext();
// Note: This requires Ribbon Workbench or similar to add the button
// Sample action when custom button is clicked
function customButtonAction() {
var subgrid = formContext.getControl("Contacts");
if (subgrid) {
var selectedRecords = subgrid.getGrid().getSelectedRows();
console.log("Selected Contacts: " + selectedRecords.getLength());
}
}
// Placeholder for triggering the custom action
console.log("Custom button action ready. Configure via Ribbon Workbench.");
}
3. Validate Subgrid Records
Prevent form save if a subgrid (e.g., Contacts) has fewer than a minimum number of records.
function validateSubgridRecords(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Contacts subgrid
var subgrid = formContext.getControl("Contacts");
if (subgrid) {
var gridRows = subgrid.getGrid().getTotalRecordCount();
if (gridRows < 2) {
executionContext.getEventArgs().preventDefault(); // Block save
formContext.ui.setFormNotification(
"At least 2 contacts are required.",
"ERROR",
"subgridValidation"
);
} else {
formContext.ui.clearFormNotification("subgridValidation");
}
}
}
4. Open a Quick Create Form
Open a quick create form for a related entity (e.g., Contact) from the Account form.
function openQuickCreateContact(executionContext) {
var formContext = executionContext.getFormContext();
// Define quick create parameters
var quickCreateParams = {
entityName: "contact",
defaultValues: {
parentcustomerid: {
id: formContext.data.entity.getId(),
entityType: "account",
name: formContext.getAttribute("name").getValue()
}
}
};
// Open the quick create form
Xrm.Navigation.openForm(quickCreateParams).then(
function() { console.log("Quick create form opened."); },
function(error) { console.log("Error: " + error.message); }
);
}
5. Set Default Values Based on Form Type
Set default field values when the form is in Create mode.
function setDefaultValues(executionContext) {
var formContext = executionContext.getFormContext();
// Check if form is in Create mode (formType = 1)
if (formContext.ui.getFormType() === 1) {
// Set default values
formContext.getAttribute("accountcategorycode").setValue(1); // Preferred Customer
formContext.getAttribute("donotemail").setValue(false); // Allow Email
console.log("Default values set for new account.");
}
}
6. Copy Field Value to Another Field
Copy a field value (e.g., Main Phone to Fax) when a condition is met.
function copyPhoneToFax(executionContext) {
var formContext = executionContext.getFormContext();
// Copy Telephone to Fax if Fax is empty
var phone = formContext.getAttribute("telephone1").getValue();
var fax = formContext.getAttribute("fax").getValue();
if (phone && !fax) {
formContext.getAttribute("fax").setValue(phone);
console.log("Telephone copied to Fax.");
}
}
7. Highlight a Field Based on Value
Change a field’s background color based on its value (requires CSS injection).
function highlightField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Revenue field control
var revenueControl = formContext.getControl("revenue");
var revenueValue = formContext.getAttribute("revenue").getValue();
// Apply custom CSS based on value
if (revenueValue > 100000) {
revenueControl.getAttribute().fireOnChange(); // Ensure UI updates
revenueControl.getControl().getElement().style.backgroundColor = "#90EE90"; // Light green
} else {
revenueControl.getControl().getElement().style.backgroundColor = ""; // Reset
}
}
8. Execute a Workflow Programmatically
Trigger a workflow for the current record using Web API.
function triggerWorkflow(executionContext) {
var formContext = executionContext.getFormContext();
var recordId = formContext.data.entity.getId().replace("{", "").replace("}", "");
// Workflow ID (replace with actual workflow GUID)
var workflowId = "{YOUR-WORKFLOW-GUID}";
// Execute workflow via Web API
var request = {
entity: { entityType: "account", id: recordId },
workflowId: workflowId
};
Xrm.WebApi.online.execute(request).then(
function() { console.log("Workflow executed successfully."); },
function(error) { console.log("Error executing workflow: " + error.message); }
);
}
9. Check User Security Roles
Perform actions based on the user’s security roles.
function checkUserRoles(executionContext) {
var formContext = executionContext.getFormContext();
var userRoles = Xrm.Utility.getGlobalContext().userSettings.roles;
// Check if user has a specific role (e.g., "System Administrator")
var hasAdminRole = false;
userRoles.forEach(function(role) {
if (role.name === "System Administrator") {
hasAdminRole = true;
}
});
// Show a section only for admins
var section = formContext.ui.tabs.get("tab_general").sections.get("section_admin");
section.setVisible(hasAdminRole);
console.log("Admin role check: " + hasAdminRole);
}
10. Auto-Generate Account Number
Generate a unique account number based on a prefix and counter.
function generateAccountNumber(executionContext) {
var formContext = executionContext.getFormContext();
// Only generate on Create form
if (formContext.ui.getFormType() === 1) {
var accountName = formContext.getAttribute("name").getValue();
if (accountName) {
// Simple logic: Prefix + random number
var prefix = "ACC-";
var randomNum = Math.floor(1000 + Math.random() * 9000); // 4-digit random
var accountNumber = prefix + randomNum;
// Set the account number field (e.g., "accountnumber")
formContext.getAttribute("accountnumber").setValue(accountNumber);
console.log("Generated Account Number: " + accountNumber);
}
}
}
Advanced:
1. Dynamic Form Navigation
Redirect users to a specific tab or section based on field values.
function navigateFormDynamically(executionContext) {
var formContext = executionContext.getFormContext();
// Get the revenue value
var revenue = formContext.getAttribute("revenue").getValue() || 0;
// Navigate to appropriate tab based on revenue
if (revenue > 100000) {
formContext.ui.tabs.get("tab_details").setFocus(); // Focus on Details tab
formContext.ui.tabs.get("tab_details").setDisplayState("expanded");
console.log("Navigated to Details tab for high revenue.");
} else {
formContext.ui.tabs.get("tab_general").setFocus(); // Focus on General tab
formContext.ui.tabs.get("tab_general").setDisplayState("expanded");
console.log("Navigated to General tab for low revenue.");
}
}
2. Real-Time Field Validation
Validate field formats (e.g., email) in real-time using regular expressions.
function validateEmailField(executionContext) {
var formContext = executionContext.getFormContext();
// Get the email field value
var email = formContext.getAttribute("emailaddress1").getValue();
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // Basic email regex
// Validate and show notification
if (email && !emailRegex.test(email)) {
formContext.getControl("emailaddress1").setNotification(
"Please enter a valid email address.",
"emailValidation"
);
} else {
formContext.getControl("emailaddress1").clearNotification("emailValidation");
}
}
3. Integration with External APIs
Call an external API to fetch data (e.g., company info from a public API).
function fetchExternalData(executionContext) {
var formContext = executionContext.getFormContext();
// Get the account name to use in the API call
var accountName = formContext.getAttribute("name").getValue();
if (!accountName) return;
// Example: Call a dummy external API (replace with real endpoint)
var apiUrl = "https://api.example.com/company?name=" + encodeURIComponent(accountName);
fetch(apiUrl, {
method: "GET",
headers: { "Content-Type": "application/json" }
})
.then(response => response.json())
.then(data => {
// Assuming the API returns revenue data
formContext.getAttribute("revenue").setValue(data.revenue || 0);
console.log("External data fetched: " + JSON.stringify(data));
})
.catch(error => {
console.log("Error fetching external data: " + error.message);
});
}
4. Custom Grid Filtering
Apply an advanced filter to a subgrid (e.g., show only active contacts).
function filterSubgrid(executionContext) {
var formContext = executionContext.getFormContext();
// Get the Contacts subgrid
var subgrid = formContext.getControl("Contacts");
if (subgrid) {
// Define FetchXML to filter active contacts only
var fetchXml = "";
// Apply the filter
subgrid.setFilterXml(fetchXml);
subgrid.refresh();
console.log("Subgrid filtered to show only active contacts.");
}
}
5. Form Timer
Display a countdown timer or track time spent on the form.
function startFormTimer(executionContext) {
var formContext = executionContext.getFormContext();
// Initialize timer (in seconds)
var timeSpent = 0;
// Update timer every second
var timer = setInterval(function() {
timeSpent++;
var minutes = Math.floor(timeSpent / 60);
var seconds = timeSpent % 60;
var timeDisplay = minutes + "m " + seconds + "s";
// Display time in a custom field or notification
formContext.ui.setFormNotification(
"Time spent on form: " + timeDisplay,
"INFO",
"timerNotification"
);
}, 1000);
// Optional: Stop timer on save (call this in OnSave event)
// clearInterval(timer);
}
6. Bulk Field Updates
Update multiple fields at once based on a single condition.
function bulkFieldUpdate(executionContext) {
var formContext = executionContext.getFormContext();
// Check if Category is "Preferred Customer" (value = 1)
var category = formContext.getAttribute("accountcategorycode").getValue();
if (category === 1) {
// Bulk update fields
formContext.getAttribute("creditlimit").setValue(100000); // Set Credit Limit
formContext.getAttribute("donotemail").setValue(false); // Allow Email
formContext.getAttribute("donotphone").setValue(false); // Allow Phone
console.log("Bulk updated fields for Preferred Customer.");
}
}
7. Custom Error Handling
Create a centralized error logging mechanism for form scripts.
function customErrorHandler(executionContext, functionName, error) {
var formContext = executionContext.getFormContext();
// Log error details
var errorMessage = "Error in " + functionName + ": " + error.message;
console.error(errorMessage);
// Display error to user
formContext.ui.setFormNotification(
"An error occurred: " + error.message + ". Please contact support.",
"ERROR",
"error_" + functionName
);
// Optional: Log to a custom entity via Web API
var errorLog = {
"new_errorname": functionName,
"new_errormessage": error.message,
"new_timestamp": new Date().toISOString()
};
Xrm.WebApi.createRecord("new_errorlog", errorLog).then(
function() { console.log("Error logged to custom entity."); },
function(err) { console.log("Failed to log error: " + err.message); }
);
}
// Example usage in another function
function sampleFunction(executionContext) {
try {
var formContext = executionContext.getFormContext();
var invalidField = formContext.getAttribute("nonexistent_field").getValue(); // Will throw error
} catch (error) {
customErrorHandler(executionContext, "sampleFunction", error);
}
}
Notes:
- Always pass
executionContext
as a parameter to accessformContext
. Enable the "Pass execution context as first parameter" option when registering the script in the form event handler.
Business Rule vs JavaScript