Every form script in Dynamics 365 CE, no matter what it's trying to accomplish, starts from the same single object: the form context. Whether you're reading a value, hiding a section, or checking whether the record is new, you go through this one object to do it. It's the foundation everything else in this course builds on.
- Reach it via executionContext.getFormContext(), passed into every handler
- Attributes hold a field's data; controls hold how that field is displayed
- It replaced the older global Xrm.Page pattern still seen in legacy code
- Also exposes form-level info: record state, form type, and a
uiarea
One remote control for the whole screen
Picture a TV remote: one control, with a button for everything you're allowed to do to the screen in front of you. The form context works the same way for a Dynamics 365 CE form.
Your script never reaches directly into the page's raw HTML to change what the user sees. Instead, it calls methods on the form context — a consistent set of "buttons" for reading values, changing values, and adjusting what's visible, no matter which table's form you're scripting.
Where the form context comes from
Almost every form event handler receives an execution context as its first parameter. You get the form context by calling executionContext.getFormContext() on it.
From there, two areas matter most:
- Attributes — a field's underlying data value ("the number 42")
- Controls — how that field is actually rendered on the form ("the visible box on screen showing 42")
That split matters: you can, for instance, hide a control without touching the underlying attribute value at all.
function onLoadHandler(executionContext) {
var formContext = executionContext.getFormContext();
// Read a value via the attribute
var priority = formContext.getAttribute("prioritycode").getValue();
// Set a different field's value
if (priority === 1) {
formContext.getAttribute("escalated").setValue(true);
}
// Show or hide a control
formContext.getControl("internalnotes").setVisible(priority === 1);
}
The most-used formContext methods (cheat sheet)
You don't need to memorize the entire Client API to be productive — a small set of methods covers most real scripts. These are the exact method names Microsoft's documentation uses, grouped by which part of the form context they live on.
Attribute methods — formContext.getAttribute("fieldname")
An attribute represents a field's underlying data — the value itself, independent of how (or whether) it's displayed.
| Method | What it does |
|---|---|
.getValue() | Returns the field's current value |
.setValue(value) | Sets the field's value |
.getRequiredLevel() | Returns "none", "recommended", or "required" |
.setRequiredLevel(level) | Sets the requirement level to one of those same three strings |
.getIsDirty() | True if this specific field has unsaved changes |
.fireOnChange() | Manually runs this field's OnChange handlers, as if the user had just changed it |
.addOnChange(handler) | Registers an additional function to run whenever this field changes |
Control methods — formContext.getControl("fieldname")
A control represents how a field is displayed — the visible box on the form, separate from the data inside it.
| Method | What it does |
|---|---|
.setVisible(true/false) | Shows or hides the field on the form |
.setDisabled(true/false) | Makes the field read-only (or editable again) |
.setLabel(text) | Changes the field's on-screen label |
.setFocus() | Moves the cursor into this field |
.setNotification(message, uniqueId) | Shows a small warning icon with a tooltip next to the field |
.clearNotification(uniqueId) | Removes a notification set with the method above |
Entity/data methods — formContext.data.entity and formContext.data
| Method | What it does |
|---|---|
formContext.data.entity.getId() | The record's unique ID (empty on a brand-new, unsaved record) |
formContext.data.entity.getEntityName() | The logical name of the table this form belongs to |
formContext.data.entity.getIsDirty() | True if anything on the whole form has unsaved changes |
formContext.data.save() | Saves the record from script (used sparingly — usually the user's own Save click is enough) |
formContext.data.refresh(save) | Reloads the form's data, optionally saving first |
UI methods — formContext.ui
| Method | What it does |
|---|---|
formContext.ui.getFormType() | Returns a number for Create, Update, Read-Only, and so on — useful for "only run this on a new record" logic |
formContext.ui.setFormNotification(message, level, id) | Shows a banner across the top of the whole form (level is "ERROR", "WARNING", or "INFO") |
formContext.ui.clearFormNotification(id) | Removes a banner set with the method above |
formContext.ui.tabs.get("tabname").setVisible(bool) | Shows or hides an entire tab |
formContext.ui.tabs.get("tabname").sections.get("name").setVisible(bool) | Shows or hides one section within a tab |
function lockDiscountField(executionContext) {
var formContext = executionContext.getFormContext();
var control = formContext.getControl("discountpercent");
control.setDisabled(true);
control.setNotification("Locked after approval", "discount-locked");
formContext.ui.setFormNotification(
"This deal has been approved and can no longer be edited.",
"WARNING",
"approved-banner"
);
}
A note on Xrm.Page
Older Dynamics 365 CE code, blog posts, or a colleague's script from a few years back will very likely use Xrm.Page instead of a form context parameter. Xrm.Page was the earlier way of reaching the same information — a single global object standing in for "the form currently open."
It still works in many environments for backward compatibility. But Microsoft's current guidance is the form context pattern shown above, passed explicitly into each handler through the execution context. You'll still recognize Xrm.Page on sight — it's reaching for the same remote control, just through an older doorway.
What else lives on the form context
Beyond attributes and controls, the form context also exposes form-level information:
- Whether the record is new or has unsaved changes, via
formContext.data.entity - The current form's type
- A
formContext.uiarea for tabs, sections, and the form's overall notification area
You won't use all of it in every script. But knowing it's all reachable from one starting object — rather than scattered across a dozen different entry points — is exactly what makes the form context predictable once you've used it a few times.
executionContext.getFormContext() — attributes hold a field's data, controls hold how that field is displayed. It's the modern replacement for the older Xrm.Page pattern you'll still see in legacy code.