Skip to content
Abhishek Chandrashekar

Dataverse JavaScript Cheatsheet

A field-by-field map of Dataverse client scripting: execution context, form context, attributes, controls, and the Xrm calls you use most.

Dynamics365,Dataverse,PowerPlatform15min read

A Dataverse form script starts at the event handler. Register it with Pass execution context as first parameter, get the form context once, then read the form and call Xrm from there.

var Contoso = window.Contoso || {};
Contoso.Account = Contoso.Account || {};
Contoso.Account.onLoad = function (executionContext) {
var formContext = executionContext.getFormContext();
var globalContext = Xrm.Utility.getGlobalContext();
var name = formContext.getAttribute("name").getValue();
};

Xrm.Page is deprecated. Always go through executionContext.getFormContext(). The rest of the deprecated calls are listed at the end.

Everything about the event that fired is on executionContext.

FieldCodeWhat it tells you
Form contextexecutionContext.getFormContext()Entry point to the form or grid the event ran on
Event sourceexecutionContext.getEventSource()Object that raised the event: the attribute on OnChange, the form on OnLoad, the grid row on grid events
DepthexecutionContext.getDepth()Position of this handler in the chain of handlers for the event
Event argsexecutionContext.getEventArgs()Event-specific arguments. Populated for OnSave, OnPostSave, OnLoad, and lookup tag events; null for most others
Set shared variableexecutionContext.setSharedVariable("key", value)Pass a value to later handlers of the same event
Get shared variableexecutionContext.getSharedVariable("key")Read a value an earlier handler stored

Read these from executionContext.getEventArgs() in an OnSave handler.

FieldCodeWhat it tells you
Save modeeventArgs.getSaveMode()Why the save happened: 1 Save, 2 Save and Close, 59 Save and New, 70 AutoSave, 5 Deactivate, 6 Reactivate, 47 Assign
Cancel the saveeventArgs.preventDefault()Stops the save. Show a notification so the user knows why
Was it cancelledeventArgs.isDefaultPrevented()True when an earlier handler already called preventDefault()
Cancel on erroreventArgs.preventDefaultOnError()Stops the save only if an error occurs, including an async OnSave handler that rejects

FieldCodeWhat it tells you
Data load stateeventArgs.getDataLoadState()1 initial load, 2 save, 3 refresh

Everything about the current record is on formContext.data.entity.

FieldCodeWhat it tells you
IdformContext.data.entity.getId()GUID of the record, wrapped in braces. Empty string on Create
Entity nameformContext.data.entity.getEntityName()Logical name of the table (account, contact, and so on)
Entity referenceformContext.data.entity.getEntityReference(){ id, entityType, name } for the record, ready to put into a lookup
Primary valueformContext.data.entity.getPrimaryAttributeValue()Value of the primary name column
Is dirtyformContext.data.entity.getIsDirty()True when any column has unsaved changes
Is validformContext.data.entity.isValid()False when a required column is empty or a value is invalid
AttributesformContext.data.entity.attributesCollection of every column on the form

CallCodeWhat it does
SaveformContext.data.save()Save the record. Returns a promise
Save and closeformContext.data.save({ saveMode: 2 })Save with a specific save mode
RefreshformContext.data.refresh(true)Reload data without reloading the form. true saves first. Returns a promise
Add OnSaveformContext.data.entity.addOnSave(handler)Attach an OnSave handler at runtime
Remove OnSaveformContext.data.entity.removeOnSave(handler)Detach it
Add OnPostSaveformContext.data.entity.addOnPostSave(handler)Run code after the save completes
Add OnLoadformContext.data.addOnLoad(handler)Run code each time data loads, including after save and refresh

Get a column with formContext.getAttribute("logicalname"). It returns null when the column is not on the form.

FieldCodeWhat it tells you
Get valueattribute.getValue()Current value. Lookups return an array; option sets return the number
Set valueattribute.setValue(value)Change the value. Does not fire OnChange
Fire OnChangeattribute.fireOnChange()Run the OnChange handlers after setValue
Nameattribute.getName()Logical name of the column
Typeattribute.getAttributeType()string, memo, integer, decimal, money, boolean, datetime, lookup, optionset, multiselectoptionset
Is dirtyattribute.getIsDirty()True when this column has unsaved changes
Controlsattribute.controlsEvery control on the form bound to this column

FieldCodeWhat it tells you
Required levelattribute.setRequiredLevel("required")none, required, or recommended. Read it with getRequiredLevel()
Submit modeattribute.setSubmitMode("always")always, never, or dirty. Use always to send a read-only value on save
Add OnChangeattribute.addOnChange(handler)Attach an OnChange handler at runtime
Remove OnChangeattribute.removeOnChange(handler)Detach it

TypeCodeWhat it tells you
Lookupattribute.setValue([{ id: guid, name: "Contoso", entityType: "account" }])Always an array of objects, even for a single-value lookup
Clear lookupattribute.setValue(null)Removes the value
Option setattribute.getText()Label of the selected option. getValue() returns the number
Option listattribute.getOptions()Every { value, text } defined for the column
Selected optionattribute.getSelectedOption(){ value, text } of the current choice
Dateattribute.setValue(new Date())Pass a JavaScript Date
Two optionsattribute.setValue(true)Pass a boolean

Get a control with formContext.getControl("logicalname"). A column on the form twice has a second control named logicalname1.

FieldCodeWhat it tells you
Show or hidecontrol.setVisible(false)Read it with getVisible()
Lock or unlockcontrol.setDisabled(true)Read it with getDisabled()
Labelcontrol.setLabel("New label")Change the label shown on the form
Focuscontrol.setFocus()Move the cursor to the control
Attributecontrol.getAttribute()Column the control is bound to
Control typecontrol.getControlType()standard, lookup, optionset, subgrid, webresource, iframe, and so on

FieldCodeWhat it tells you
Field errorcontrol.setNotification("Message", "uniqueId")Red error on the field. Blocks save until cleared
Clear itcontrol.clearNotification("uniqueId")Remove that notification
Recommendationcontrol.addNotification({ messages: ["Message"], notificationLevel: "RECOMMENDATION", uniqueId: "id", actions: [...] })Light-bulb hint with optional actions. Use ERROR for a blocking error

FieldCodeWhat it tells you
Before searchcontrol.addPreSearch(handler)Runs before the lookup shows results. Add filters here
Filter resultscontrol.addCustomFilter(fetchXmlFilter, "account")Add a <filter> block. Call it only inside a PreSearch handler
Remove PreSearchcontrol.removePreSearch(handler)Detach the handler
Custom viewcontrol.addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, isDefault)Add a view built from FetchXML to the lookup

FieldCodeWhat it tells you
Remove optioncontrol.removeOption(value)Hide one choice from the dropdown
Add optioncontrol.addOption({ value: 1, text: "Label" }, index)Add a choice back. It must exist in the column definition
Clear optionscontrol.clearOptions()Remove every choice from the dropdown

FieldCodeWhat it tells you
Refreshcontrol.refresh()Reload the subgrid rows
Gridcontrol.getGrid()Access rows through getRows() and getSelectedRows()
Row countcontrol.getGrid().getTotalRecordCount()Number of records in the subgrid
On loadcontrol.addOnLoad(handler)Runs every time the subgrid loads or refreshes

FieldCodeWhat it tells you
Form typeformContext.ui.getFormType()0 Undefined, 1 Create, 2 Update, 3 Read Only, 4 Disabled, 6 Bulk Edit
Current formformContext.ui.formSelector.getCurrentItem()Current main form. Use getId() and getLabel() on it
Switch formformContext.ui.formSelector.items.get(formId).navigate()Open another main form for the same record
CloseformContext.ui.close()Close the form
Refresh ribbonformContext.ui.refreshRibbon()Re-evaluate command bar enable and display rules

FieldCodeWhat it tells you
ShowformContext.ui.setFormNotification("Message", "WARNING", "uniqueId")Banner at the top of the form. Level is ERROR, WARNING, or INFO
ClearformContext.ui.clearFormNotification("uniqueId")Remove that banner

FieldCodeWhat it tells you
TabformContext.ui.tabs.get("tabName")Tab by the name set in the form designer
Show or hide tabtab.setVisible(false)Hides the tab and everything in it
Expand or collapsetab.setDisplayState("collapsed")expanded or collapsed
Focus tabtab.setFocus()Select the tab
Sectiontab.sections.get("sectionName")Section inside that tab
Show or hide sectionsection.setVisible(false)Hides the section and its controls
Tab changetab.addTabStateChange(handler)Runs when the tab expands or collapses

Every call returns a promise. Use Xrm.WebApi for online and offline; use Xrm.WebApi.online for execute.

CallCodeWhat it does
CreateXrm.WebApi.createRecord("account", data)Insert a record. Resolves to { entityType, id }
RetrieveXrm.WebApi.retrieveRecord("account", id, "?$select=name,revenue")Read one record. Always use $select
RetrieveMultipleXrm.WebApi.retrieveMultipleRecords("account", "?$select=name&$filter=statecode eq 0", 50)Query with OData. Resolves to { entities, nextLink }
FetchXMLXrm.WebApi.retrieveMultipleRecords("account", "?fetchXml=" + encodeURIComponent(fetchXml))Query with FetchXML
UpdateXrm.WebApi.updateRecord("account", id, data)Write only the properties in data
DeleteXrm.WebApi.deleteRecord("account", id)Remove a record
ExecuteXrm.WebApi.online.execute(request)Send an action, function, or custom API request
Execute batchXrm.WebApi.online.executeMultiple(requests)Send several requests together. Nest an array for a change set

UseCodeWhat it tells you
Set a lookup"parentcustomerid_account@odata.bind": "/accounts(" + id + ")"Navigation property name plus the entity set name
Clear a lookupXrm.WebApi.updateRecord("contact", id, { "parentcustomerid_account": null })Use the single-valued navigation property name
Read a lookupresult["_parentcustomerid_value"]GUID of the related record
Lookup labelresult["_parentcustomerid_value@OData.Community.Display.V1.FormattedValue"]Display name of the related record
Option labelresult["industrycode@OData.Community.Display.V1.FormattedValue"]Label for an option set value
Strip bracesid.replace(/[{}]/g, "")getId() returns braces; the Web API does not want them

execute needs a request object with getMetadata.

var request = {
Target: { entityType: "account", id: accountId },
getMetadata: function () {
return {
boundParameter: "entity",
parameterTypes: {
Target: { typeName: "mscrm.account", structuralProperty: 5 }
},
operationType: 0, // 0 action, 1 function, 2 CRUD
operationName: "contoso_RecalculateCredit"
};
}
};
Xrm.WebApi.online.execute(request)
.then(function (response) { return response.json(); })
.then(function (result) { console.log(result); });

Use boundParameter: null and drop Target for an unbound custom API.

CallCodeWhat it does
AlertXrm.Navigation.openAlertDialog({ title: "Title", text: "Message" })One-button dialog. Resolves when closed
ConfirmXrm.Navigation.openConfirmDialog({ title: "Title", text: "Continue?" })Resolves to { confirmed: true/false }
ErrorXrm.Navigation.openErrorDialog({ message: "Message", details: "Stack" })Error dialog with a downloadable details file

CallCodeWhat it does
Open formXrm.Navigation.openForm({ entityName: "account", entityId: id })Open a record. Drop entityId to open a new one
Quick createXrm.Navigation.openForm({ entityName: "contact", useQuickCreateForm: true }, defaults)Open quick create with default values
NavigateXrm.Navigation.navigateTo({ pageType: "entityrecord", entityName: "account", entityId: id }, { target: 2, position: 1, width: { value: 50, unit: "%" } })target: 2 opens a modal dialog; position: 2 makes it a side dialog
Open listXrm.Navigation.navigateTo({ pageType: "entitylist", entityName: "account" })Go to a table’s grid view
Custom pageXrm.Navigation.navigateTo({ pageType: "custom", name: "contoso_mypage_12345" }, { target: 2 })Open a canvas custom page
Web resourceXrm.Navigation.navigateTo({ pageType: "webresource", webresourceName: "contoso_/page.html", data: "id=1" }, { target: 2 })Open an HTML web resource in a dialog
URLXrm.Navigation.openUrl("https://contoso.com")Open an external URL in a new window

CallCodeWhat it does
Global contextXrm.Utility.getGlobalContext()User, organization, and client information
Show spinnerXrm.Utility.showProgressIndicator("Working...")Blocking progress indicator
Hide spinnerXrm.Utility.closeProgressIndicator()Close it. Call it in both success and error paths
Lookup dialogXrm.Utility.lookupObjects({ entityTypes: ["account"], allowMultiSelect: false })Resolves to the selected { id, name, entityType } array
MetadataXrm.Utility.getEntityMetadata("account", ["industrycode"])Table and column metadata, including option set labels
Localized stringXrm.Utility.getResourceString("contoso_/strings", "key")Read a value from a RESX web resource
Page contextXrm.Utility.getPageContext()Current page input, such as entity name and id
Status transitionsXrm.Utility.getAllowedStatusTransitions("incident", stateCode)Status reasons allowed from the given state

Read these from Xrm.Utility.getGlobalContext().

FieldCodeWhat it tells you
UserIdglobalContext.userSettings.userIdGUID of the signed-in user
UserNameglobalContext.userSettings.userNameDisplay name of the signed-in user
RolesglobalContext.userSettings.rolesCollection of { id, name } security roles. Use forEach or get
LanguageIdglobalContext.userSettings.languageIdLCID of the user’s UI language (1033 English)
Time zoneglobalContext.userSettings.getTimeZoneOffsetMinutes()User’s offset from UTC in minutes

FieldCodeWhat it tells you
Client URLglobalContext.getClientUrl()Base URL of the environment. Use it to build Web API URLs
Unique nameglobalContext.organizationSettings.uniqueNameUnique name of the environment
Organization idglobalContext.organizationSettings.organizationIdGUID of the organization
Base currencyglobalContext.organizationSettings.baseCurrency{ id, name, entityType } of the base currency
VersionglobalContext.getVersion()Dataverse version number
Current appglobalContext.getCurrentAppProperties()Promise resolving to the model-driven app’s appId, displayName, and uniqueName

FieldCodeWhat it tells you
ClientglobalContext.client.getClient()Web, Outlook, or Mobile
Form factorglobalContext.client.getFormFactor()0 Unknown, 1 Desktop, 2 Tablet, 3 Phone
OfflineglobalContext.client.isOffline()True when running offline in the mobile app

CallCodeWhat it does
Global bannerXrm.App.addGlobalNotification({ type: 2, level: 3, message: "Message", showCloseButton: true })App-level banner. Level 1 success, 2 error, 3 warning, 4 info. Resolves to an id
Clear bannerXrm.App.clearGlobalNotification(id)Remove that banner
Side paneXrm.App.sidePanes.createPane({ title: "Details", paneId: "details", canClose: true })Add a side pane. Call navigate(pageInput) on it to load content

Pass PrimaryControl as a CRM parameter on the command. On a form it is the form context; on a grid it is the grid context.

UseCodeWhat it tells you
Form commandfunction run(primaryControl) { var formContext = primaryControl; }Same object as executionContext.getFormContext()
Selected idsPass SelectedControlSelectedItemIdsArray of GUIDs of the selected grid rows
Enable rulefunction isEnabled(primaryControl) { return true; }Return a boolean or a promise that resolves to one
Re-evaluateformContext.ui.refreshRibbon()Run enable and display rules again after a value changes

These calls still run. Microsoft has not removed them, and Xrm.Page will stay longer than the others because so many scripts still use it. New scripts should call the replacement.

DeprecatedUse insteadWhat changed
Xrm.PageexecutionContext.getFormContext()On a command, pass PrimaryControl. parent.Xrm.Page still works from an HTML web resource embedded on a form
Xrm.Page.contextXrm.Utility.getGlobalContext()Global context no longer hangs off the form
Xrm.Page.context.getQueryStringParameters()formContext.data.attributesQuery-string values and openForm parameters arrive as attributes
formContext.data.entity.save()formContext.data.save()Save moved onto formContext.data
Xrm.Page.data.entity.getDataXml()Same methodOn a lookup, read typename, not type

globalContext is Xrm.Utility.getGlobalContext().

DeprecatedUse insteadWhat changed
getTimeZoneOffsetMinutes()globalContext.userSettings.getTimeZoneOffsetMinutes()Moved to user settings
getUserId()globalContext.userSettings.userIdMoved to user settings
getUserLcid()globalContext.userSettings.languageIdMoved to user settings
getUserName()globalContext.userSettings.userNameMoved to user settings
getUserRoles()globalContext.userSettings.rolessecurityRoles was the first replacement, and it is deprecated too
getIsAutoSaveEnabled()globalContext.organizationSettings.isAutoSaveEnabledMoved to organization settings
getOrgLcid()globalContext.organizationSettings.languageIdMoved to organization settings
getOrgUniqueName()globalContext.organizationSettings.uniqueNameMoved to organization settings
userSettings.securityRolesuserSettings.rolesroles includes the display name, not only the GUID
userSettings.transactionCurrencyIduserSettings.transactionCurrencyReturns { id, name, entityType }
organizationSettings.baseCurrencyIdorganizationSettings.baseCurrencyReturns { id, name, entityType }
DeprecatedUse insteadWhat changed
Xrm.Utility.alertDialogXrm.Navigation.openAlertDialogReturns a promise, same shape as the other navigation calls
Xrm.Utility.confirmDialogXrm.Navigation.openConfirmDialogResolves to { confirmed }
Xrm.Utility.openEntityFormXrm.Navigation.openFormNavigation lives on Xrm.Navigation
Xrm.Utility.openQuickCreateXrm.Navigation.openFormPass useQuickCreateForm: true
Xrm.Utility.openWebResourceXrm.Navigation.openWebResourceOn Unified Interface this returns nothing
Xrm.Utility.getBarcodeValueXrm.Device.getBarcodeValueDevice calls live on Xrm.Device
Xrm.Utility.getCurrentPositionXrm.Device.getCurrentPositionDevice calls live on Xrm.Device
Xrm.Utility.isActivityTypeXrm.Utility.getEntityMetadataThe replacement is async, so it cannot run inside a ribbon rule
Xrm.Mobile.offlineXrm.WebApi.offlineOffline calls live on Xrm.WebApi

DeprecatedUse insteadWhat changed
addOnKeyPressA Power Apps component framework controlNo client-API replacement
fireOnKeyPressA Power Apps component framework controlNo client-API replacement
removeOnKeyPressA Power Apps component framework controlNo client-API replacement
showAutoCompleteA Power Apps component framework controlNo client-API replacement
hideAutoCompleteA Power Apps component framework controlNo client-API replacement
GridRow.getData()GridRow.dataSame shape as formContext.data
GridRowData.getEntity()GridRowData.entitySame shape as formContext.data.entity
getObject()getContentWindow()On an HTML web resource control
parent.Xrmcontrol.getContentWindow()parent.Xrm only works while the web resource is inside a form. A new window uses opener.Xrm

DeprecatedUse insteadWhat changed
getData and setData on a Silverlight web resourceNoneSilverlight is unsupported. These methods were removed after October 2020

Source: Some client APIs are deprecated.

Leave secrets and API keys out of web resources. Anything in client script is readable by the user.