Useful Javascript Methods in Microsoft Dynamics 365
Useful Javascript Methods in Microsoft Dynamics 365
Mohit Baldawa
In this Document, I had listed out the most useful JavaScript methods that are
used in Dynamic 365 CRM. This is quick reference guide covering Microsoft
Dynamics CRM syntax of common java script requirements for learning client-side
scripting in Dynamic CRM. Keeping that in my mind, I am listing few methods that
one should be handy and ready with.
Most of the examples are provided as functions that you can easily test in the On
Load and On Save by generating form Context from execution Context
1. Context methods:
UserId: This retrieves the unique identifier (GUID) of the currently logged-in user.
UserName: This fetches the full name of the user who is currently logged in.
OrgName: Retrieves the unique name of the organization (CRM instance).
ClientUrl: Returns the base URL of the organization (e.g., https://org.crm.dynamics.com).
CurrentUserRoles: Fetches a list of GUIDs representing the security roles assigned to
the logged-in user.
UserLanguageId: It retrieves the LCID (Locale Identifier) for the currently logged-in
user, which corresponds to the user’s regional settings and language preferences
EntityId: Retrieves the unique identifier (GUID) of the currently open record in the
form. It is essential for identifying the current record, especially when making API
calls or performing specific actions related to it.
EntityIdWithoutBraces: Retrieves the GUID and removes the curly braces {}
surrounding it, which might be necessary for some API calls. It prepares the GUID
for use in APIs or external integrations that require the ID without curly braces.
EntityName: Retrieves the logical name of the entity (like account, contact, etc.)
for the currently open record. It is useful for identifying the type of entity you're
working with, especially in custom scripts or workflows.
EntitySetName: Retrieves the OData entity set name (e.g., accounts, contacts) of
the current record. It is needed when working with the Web API or making OData
requests to interact with entities.
IsDirty: Returns true if the record has unsaved changes, otherwise returns false. It
is useful for checking if a user has modified the form and potentially preventing
navigation away from the record without saving.
AttrName: Retrieves the value of the primary attribute (e.g., Name for an account
or contact) of the current record. It is helpful for displaying or using the primary
attribute in custom logic, workflows, or UI elements.
function retrieveEntityInfo(executionContext)
{
var entityId = formContext.data.entity.getId();
var entityIdWithoutBraces = formContext.data.entity.getId().replace('{',
'').replace('}', '');
var entityName = formContext.data.entity.getEntityName();
var entitySetName = formContext.data.entity.getEntitySetName();
var isDirty = formContext.data.entity.getIsDirty();
var AttrName = formContext.data.entity.getPrimaryAttributeValue();
}
Mohit Baldawa
• Refresh Form Data: Refreshes the form data to ensure that it reflects the latest
data from the database. It can be useful if changes to the record might have been
made externally or via workflows, and you want the form to display updated
values.
• Refresh Ribbon: Refreshes the ribbon (command bar) of the form to reflect any
changes in the state of commands or buttons. Use this method after modifying
data or setting form values that might impact ribbon button enablement or
visibility.
• Save the Record: Saves the current record to the database. Used when you want
to ensure the record's data is persisted without additional actions like closing the
form or creating a new record.
• Save and Close: Saves the current record and then closes the form. Ideal for
workflows where the user has completed editing and does not need to remain on
the form. Ideal for workflows where the user has completed editing and does not
need to remain on the form.
• Save and Open a New Form: Saves the current record and then opens a new
form to create another record of the same entity. Commonly used in data-entry
scenarios where users need to create multiple records in succession.
function performSaveOperations(executionContext) {
var formContext = executionContext.getFormContext();
4. Field Events
• Set Focus to a Field: Sets the focus on a specific field (control) in the form. Used
to guide the user to a specific field that requires attention or input.
• Set Field to Always Submit Data: Ensures that the field's value is always
submitted when the record is saved, even if the value hasn't been modified.
Useful when the field's value must be saved regardless of whether it has changed
or not (e.g., when used in workflows or plugins).
• Fire the OnChange Event Explicitly: Explicitly triggers the OnChange event for
the specified field. Useful for programmatically triggering field-level logic without
requiring user input.
• Disable a Field: Disables the field, preventing users from editing it. Used to
enforce business rules, such as making certain fields read-only based on other
data or user roles.
• Enable a Field: Enables the field, so users can edit it.
• Get Selected Value from an OptionSet: Retrieves the value of the selected
option in an OptionSet field. Necessary for logic based on the user's selection in
an OptionSet.
function fieldOperations(executionContext) {
var formContext = executionContext.getFormContext();
• Hide a Field: Hides the specified field (control) on the form. Useful for
dynamically showing or hiding fields based on certain conditions or user roles.
• Show a Field: Shows the specified field (control) on the form. Useful for
dynamically showing or hiding fields based on certain conditions.
• Hide a Tab: Hides a specified tab on the form. Useful for managing form layout
dynamically by hiding tabs that are not relevant for a particular scenario or user.
• Hide a Section in a Tab: Hides a specific section within a tab on the form. Useful
when you want to selectively show or hide specific sections of a tab based on
conditions or business logic.
• Set a Notification: Displays a notification (message) on the specified field. Used
to alert users about invalid input, missing data, or any other important
information related to the field.
• Clear a Notification: Clears any existing notification from the specified field.
Used to remove a previously set notification after the issue is resolved or no
longer relevant.
function manageFormElements(executionContext) {
var formContext = executionContext.getFormContext();
// Hide a field
formContext.getControl("new_fieldname").setVisible(false);
// Hide a field
formContext.getControl("new_fieldname").setVisible(true);
// Hide a tab
formContext.ui.tabs.get("tab_unique_name").setVisible(false);
It is used to dynamically set the requirement level of a field based on specific business
logic or user interaction.
Requirement Levels
1. Not Required (none):
The field is optional and does not require user input before saving the
record.
Typically used for fields that provide additional information but are not
critical.
2. Business Recommended (recommended):
The field is visually indicated with a blue dashed underline, encouraging
users to fill it.
Used in scenarios where providing the data is helpful but not mandatory
for saving.
3. Business Required (required):
The field is marked with a red asterisk, enforcing that user input is
mandatory before saving.
Used for critical fields that are essential for the business process.
function setRequirementLevel(executionContext)
{
formContext.getAttribute("new_schemaName").setRequiredLevel("none");
formContext.getAttribute("new_schemaName").setRequiredLevel("recommended");
formContext.getAttribute("new_schemaName").setRequiredLevel("required");
}
Mohit Baldawa
LookupValue: Retrieves the entityType (e.g., the logical name of the referenced
entity) from the lookup field
o id: The GUID of the related record.
o name: The display name of the related record.
o entityType: The logical name of the related entity.
DateValue: Retrieves the date value from the field. It returns a JavaScript Date
object.
function retrieveFieldValues(executionContext) {
var formContext = executionContext.getFormContext();
// Lookup field
var lookupValue = formContext.getAttribute("new_accountid").getValue();
if (lookupValue && lookupValue.length > 0) {
console.log("Lookup ID:", lookupValue[0].id);
console.log("Lookup Name:", lookupValue[0].name);
console.log("Lookup Entity Type:", lookupValue[0].entityType);
}
// Text field
var textValue = formContext.getAttribute("new_employeebusinessid").getValue();
// OptionSet field
var genderValue = formContext.getAttribute("new_gender").getValue();
var genderLabel = formContext.getAttribute("new_gender").getText();
Single Line of Text: Sets the value of the new_employeebusinessid field to "abcd"
OptionSet: Sets the value of the new_gender field to 123 (the numerical database value
of the selected option).
o Ensure that 123 is a valid option value for this OptionSet field.
o Use getValue() or getText() to confirm available options.
Two Options: Sets the value of the new_type field. There are two possible options.
o true: Represents "Yes"
o false: Represents "No"
Date Field: Sets the value of the new_dateofbirth field to the current date or any specific
date also.
Lookup Field: lookup field stores references to related records. To set a value for a
lookup field, you need to provide an object containing the following properties:
o id: The GUID of the related record.
o name: The display name of the related record.
o entityType: The logical name of the related entity.
Clear Lookup Field: To clear a lookup field, set its value to null
function setFieldValues(executionContext) {
var formContext = executionContext.getFormContext();
// Date field
var specificDate = new Date(1990, 5, 15); // June 15, 1990
var dateOfBirth = new Date();
formContext.getAttribute("new_dateofbirth").setValue(dateOfBirth);
// Set Lookup value and First Define the lookup value object
var lookupValue = [{
id: "8a3b3b1d-3df8-ec11-8f8f-002248209a04",
name: "Example Account",
entityType: "account"
}];
// Set the lookup value
formContext.getAttribute("new_accountid").setValue(lookupValue);
// Clear the lookup field
formContext.getAttribute("new_accountid").setValue(null);
}
Mohit Baldawa
We can apply a filter to a lookup field to restrict the records shown in the lookup
dialog. This is useful when you want to display only specific records based on certain
criteria.
The addPreSearch() method allows you to define custom logic that runs before the
lookup dialog is displayed
Use the addCustomFilterToLookup() function to apply the filter.
Use FetchXML syntax to define the criteria for filtering records.
Then using the addCustomFilter() method will apply the filter to the lookup control.
You can specify the logical name of the entity for which the filter applies (e.g.,
"account").
If you need to clear the filter or remove the PreSearch event use
lookupControl.removePreSearch();
function filterLookupField(executionContext) {
var formContext = executionContext.getFormContext();
if (lookupControl) {
lookupControl.addPreSearch(function () {
addCustomFilterToLookup(lookupControl);
});
}
}
function addCustomFilterToLookup(lookupControl) {
// Define the filter XML
var accountName = "ABC Corp";
var filterXml =
`<filter type="and">
<condition attribute="name" operator="eq" value="${accountName}" />
</filter>`;
function getFormType(executionContext) {
var formContext = executionContext.getFormContext();
• Set a Form Notification: Displays a notification message at the top of the form.
• Parameters:
o Message: The text of the notification.
o Type: The type of notification ("ERROR", "WARNING", "INFO").
o UniqueId: A unique identifier to identify and manage the notification.
• Use Case: Inform users about errors, warnings, or important information on the
form.
• Clear a Form Notification: Removes a previously displayed notification from the
form.
• Parameters:
o UniqueId: The unique identifier of the notification to clear.
• Use Case: Used to remove notifications once the issue is resolved or no longer
relevant.
function manageFormNotifications(executionContext) {
var formContext = executionContext.getFormContext();
1) ReadOnly Function:
2) doesControlHaveAttribute Function:
• Ensures that the control is not of type "iframe", "webresource", or "subgrid", as these
control types do not have attributes and cannot be disabled like fields.
3) Usage Example
• To make all fields on the form read-only
ReadOnly(executionContext, true);
• To make all fields editable:
ReadOnly(executionContext, false);
4) Scenarios:
This approach is ideal for enforcing read-only or editable states dynamically
based on roles, statuses, or other conditions.
formContext.ui.controls.forEach(function (control) {
if (doesControlHaveAttribute(control)) {
control.setDisabled(flag);
}
});
}
function doesControlHaveAttribute(control) {
var controlType = control.getControlType();
return controlType !== "iframe" && controlType !== "webresource" && controlType
!== "subgrid";
}
Mohit Baldawa
The function is designed to manipulate the submit mode of a field, specifically to control
whether data is submitted even if the field is read-only. This method is typically used
when there is a need to ensure that a field value is included in the form submission,
even if the field is read-only or its value has not been modified by the user.
The function utilizes the setSubmitMode() method to control the submission behavior of
a field, which can be set to one of three states:
"always": The field value will always be submitted, regardless of its state.
"never": The field value will not be submitted, even if it is modified.
"dirty": The field will be submitted only if its value has been modified.
function ForceSaveDataOnReadOnlyField(executionContext) {
try {
// Get the form context
var formContext = executionContext.getFormContext();
formContext.getAttribute("new_employeetype").setSubmitMode("always");
formContext.getAttribute("new_employeetype").setSubmitMode("never");
formContext.getAttribute("new_employeetype").setSubmitMode("dirty");
} catch (e) {
// Display an alert if an error occurs
Xrm.Utility.alertDialog(e.message);
}
}
Mohit Baldawa
This function closes the current form programmatically. It is commonly used to end the
user's interaction with the form when certain conditions are met
function CloseForm(executionContext) {
try {
// Get the form context
var formContext = executionContext.getFormContext();
Xrm.Navigation.openForm({
entityName: "incident",
entityId: formContext.data.entity.getId(),
});
Mohit Baldawa
Use Case: Used to display custom web resources, like HTML or JavaScript
components, in a pop-up.
function manageStageNavigation(executionContext) {
var formContext = executionContext.getFormContext();
19. Adding Event Handlers for BPF Stage Changes and Selection
Business Process Flow (BPF) events like stage changes or stage selections can be
captured using event handlers. These event handlers allow to execute custom logic
when users interact with the process stages.
function myBPFStageHandler(executionContext) {
function myStageChangeHandler(executionContext) {
var formContext = executionContext.getFormContext();
var stage = formContext.data.process.getActiveStage();
var stageName = stage ? stage.getName() : "No active stage";
console.log("Stage changed to: " + stageName);
}
function myStageSelectedHandler(executionContext) {
var formContext = executionContext.getFormContext();
var selectedStage = formContext.data.process.getSelectedStage();
var selectedStageName = selectedStage ? selectedStage.getName() : "No selected stage";
console.log("Stage selected: " + selectedStageName);
}
}
Mohit Baldawa
This method opens a confirmation dialog box that allows users to confirm or
cancel an action.
o confirmStrings: An object defining the message (text) and the title (title) to
display in the confirmation dialog.
o confirmOptions: An object defining the size of the confirmation dialog in
terms of height and width.
It is a non-blocking, promise-based function, which makes it ideal for providing
user-friendly confirmations without halting the script execution.
You can dynamically adjust the content of the confirmation dialog based on the
record's context.
It ensures that critical updates are intentional and not accidental.
Provides a clear and interactive way for users to confirm actions.
function confirmRecordUpdate(formContext) {
Xrm.Navigation.openConfirmDialog(confirmStrings, confirmOptions).then(
function (success) {
if (success.confirmed) {
console.log(`${recordName} will be updated.`);
// Perform update logic
} else {
console.log("User canceled the update.");
}
});
}
Mohit Baldawa
This function is designed to format the current date and time in a user-friendly
12-hour clock format, appending AM/PM to indicate the period of the day.
This function is particularly useful when displaying timestamps in applications
where users expect familiar and readable date-time formats.
If the current date and time is January 25, 2025, 14:05, the function will return:
"1/25/2025 2:05 PM"
If you need the time in a specific timezone, you can use the Intl.DateTimeFormat
API for better localization.
var formattedDate = new Intl.DateTimeFormat('en-US', { dateStyle: 'short',
timeStyle: 'short' }).format(date);
function formatAMPM() {
// Extract hours and minutes and seconds from the date object
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
This function is designed to validate the "End Date" field in a form to ensure
that the end date is always later than the start date.
If the validation fails, an error notification is displayed, providing the user with
immediate feedback to correct the input.
It ensures that users cannot accidentally or intentionally input invalid dates
that violate business rules and helps to maintain clean and reliable data by
enforcing logical relationships between related fields.
Immediately alerts the user of errors during form completion, reducing the
need for post-submission error handling.
function ValidateEndDate(executionContext) {
var formContext = executionContext.getFormContext();
// Access the control of the "End Date" field for setting notifications
var endDateFieldControl = formContext.getControl("new_endDate");
// Convert the dates to remove time portions for accurate day-based comparison
startDate = new Date(startDate.toISOString().substr(0, 10));
endDate = new Date(endDate.toISOString().substr(0, 10));
// Check if the start date is greater than or equal to the end date
if (startDate >= endDate) {
// Display an error notification on the "Maintenance End Date" field
endDateFieldControl.setNotification("Cannot set start date more than end date.",
"ErrEndDate");
}
else {
// Clear the error notification if the validation passes
endDateFieldControl.clearNotification("ErrEndDate");
}
}
}
Mohit Baldawa
Navigation Items represent the links or shortcuts displayed in the navigation pane of
an entity form. These items provide users with quick access to related entities or
records, improving the overall user experience and efficiency.
function ManageNavigationItems(executionContext) {
var formContext = executionContext.getFormContext();
setTimeout(function () {
console.log("Hello after 3 seconds");
}, 3000);
This is the function for URI encoding and decoding methods to handle special
characters in URLs. This is essential when working with web applications to ensure
compatibility and avoid errors caused by invalid characters in URIs.
Avoids misinterpretation of special characters by browsers or servers.
console.log(Encoded_URI);
// Output:
https%3A%2F%2Fvicity.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab
var Encoded_URI =
"https%3A%2F%2Fvicity.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab";
var Decoded_URI = decodeURIComponent(Encoded_URI);
console.log(Decoded_URI);
// Output: https://vicity.com/my test.asp?name=ståle&car=saab
function OpenRandomUrl(url) {
if (url && typeof url === "string" && url.trim() !== "") {
window.open(url);
} else {
alert("Invalid or missing URL. Please provide a valid URL.");
}
}
Mohit Baldawa
This method displays a progress indicator with the message "Processing your
request...". The progress indicator is typically a spinner or loading screen that
prevents user interaction during long-running operations.
Once the processing is completed, we can clear the progress indicator allowing users
to interact with the system again.
function processData() {
// Show progress indicator
Xrm.Utility.showProgressIndicator("Processing your data, please wait...");
The Xrm.WebApi library is part of the Dynamics 365 Client API. It allows to perform
CRUD operations (Create, Read, Update, Delete) on entity records without manually
building HTTP requests or using server-side code.
Suppose you want to create the account record with the details
Here in accountData each key in the object corresponds to a field's logical name, and
its value is the data you want to set for that field to create record
function createAccountRecord() {
// Define the data for the new record
var accountData = {
"name": "Contoso Ltd.", // Account name
"telephone1": "555-0101", // Phone number
"websiteurl": "https://www.contoso.com" // Website
};
Always use the entity's logical name (e.g., "account", "contact") and the field's logical
names (e.g., "telephone1").
function updateAccountRecord(accountId) {
// Define the data to be updated
var updatedData = {
"telephone1": "555-1212", // New Phone Number
"websiteurl": "https://contoso-updated.com" // New Website
};
// Call Xrm.WebApi.updateRecord
Xrm.WebApi.updateRecord("account", accountId, updatedData).then(
function success(result) {
// Step 3: Handle success
console.log("Account updated successfully.");
Xrm.Utility.alertDialog("Account updated successfully.");
},
function (error) {
// Handle errors
console.error("Error while updating the account: " + error.message);
Xrm.Utility.alertDialog("Error: " + error.message);
}
);
}
Mohit Baldawa
Always use the entity's logical name (e.g., "account", "contact") and the field's logical
names (e.g., "telephone1").
function deleteAccountRecord(accountId) {
Xrm.WebApi.deleteRecord("account", accountId).then(
function success(result) {
console.log("Account deleted successfully.");
Xrm.Utility.alertDialog("Account deleted successfully.");
},
function (error) {
console.error("Error while deleting the account: " + error.message);
Xrm.Utility.alertDialog("Error: " + error.message);
}
);
}
Mohit Baldawa
Suppose if we want to retrieve all the active accounts created after January 1, 2023
we need to pass the query parameters.
Query Parameters:
o $select: Specifies the fields to retrieve.
o $filter: Filters records (e.g., statuscode eq 1 for active accounts).
o Combine filters using logical operators (and, or).
Success Callback: Loops through the retrieved records and logs their details.
Error Callback: Handles retrieval errors.
Always use the entity's logical name (e.g., "account", "contact") and the field's logical
names (e.g., "telephone1").
Use tools like the FetchXML Builder or the Web API Reference Tool to test your
queries.
function retrieveFilteredAccounts() {
// Define a query to fetch active accounts created after January 1, 2023
var query = "?$select=name,telephone1,createdon" +
"&$filter=statuscode eq 1 and createdon gt 2023-01-01T00:00:00Z";
Xrm.WebApi.retrieveMultipleRecords("account", query).then(
function success(result) {
result.entities.forEach(function (account) {
console.log("Account Name: " + account.name);
console.log("Phone: " + account.telephone1);
console.log("Created On: " + account.createdon);
});
},
function (error) {
console.error("Error retrieving accounts: " + error.message);
Xrm.Utility.alertDialog("Error: " + error.message);
}
);
}
Mohit Baldawa
Ensure the action is published and available in Dynamics 365 and know the name of
the action and its input/output parameters.
Use the OData endpoint for the action and pass required parameters in the request
body.
function callSynchronousAction() {
try {
// Define the server URL and action endpoint
var serverUrl = Xrm.Utility.getGlobalContext().getClientUrl();
var actionName = "new_UpdateContactDetails";
var actionUrl = serverUrl + "/api/data/v9.1/" + actionName;
Ensure the action is published and available in Dynamics 365 and know the name of
the action and its input/output parameters.
var data = {
CustomerId: customerId,
CaseId: caseId
};
req.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 204) {
console.log("Action executed successfully in the background.");
} else {
console.error("Error invoking the asynchronous action: ",
JSON.parse(this.response).error.message);
}
}
};
req.send(JSON.stringify(data));
}
Mohit Baldawa
thanks
Mohit Baldawa