🔒 Guided

Pre-launch preview. Authorised access only.

Incorrect code

Guided by A Guide to Cloud
Explore AB-900 AI-901
Guided PL-400 Domain 4
Domain 4 — Module 1 of 4 25%
11 of 26 overall

PL-400 Study Guide

Domain 1: Create a Technical Design

  • Solution Architecture: What Goes Where Free
  • Security by Design: Auth, Roles & DLP Free
  • Designing UX Components: Canvas, PCF & Client Scripts Free
  • Designing Platform Extensions: Connectors, Plug-ins & APIs Free
  • Integration & Automation Blueprints Free

Domain 2: Build Power Platform Solutions

  • Environment Setup & Security Troubleshooting
  • Solutions & Layers: ALM Foundations
  • CI/CD Pipelines for Power Platform

Domain 3: Implement Power Apps Improvements

  • Advanced Power Fx & Canvas Components
  • Troubleshoot & Optimise Apps

Domain 4: Extend the User Experience

  • Client Scripting: Form Events & the Client API
  • Commands, Buttons & Custom Page Navigation
  • PCF Components: Build & Lifecycle
  • PCF Components: Package, Deploy & Advanced Features

Domain 5: Extend the Platform

  • The Plug-in Pipeline: How Dataverse Processes Events Free
  • Writing Plug-ins: Business Logic, Service & Registration
  • Custom APIs & Business Events
  • Custom Connectors: OpenAPI & Authentication
  • Custom Connectors: Azure, Policies & Code
  • Dataverse APIs: Web API & Organisation Service
  • Azure Functions for Power Platform
  • Cloud Flows: Dataverse Triggers & Expressions
  • Cloud Flows: Security, Errors & Child Flows

Domain 6: Develop Integrations

  • Publishing Dataverse Events
  • Service Endpoints: Webhooks, Service Bus & Event Hub
  • Data Sync: Change Tracking, Alternate Keys & Upsert

PL-400 Study Guide

Domain 1: Create a Technical Design

  • Solution Architecture: What Goes Where Free
  • Security by Design: Auth, Roles & DLP Free
  • Designing UX Components: Canvas, PCF & Client Scripts Free
  • Designing Platform Extensions: Connectors, Plug-ins & APIs Free
  • Integration & Automation Blueprints Free

Domain 2: Build Power Platform Solutions

  • Environment Setup & Security Troubleshooting
  • Solutions & Layers: ALM Foundations
  • CI/CD Pipelines for Power Platform

Domain 3: Implement Power Apps Improvements

  • Advanced Power Fx & Canvas Components
  • Troubleshoot & Optimise Apps

Domain 4: Extend the User Experience

  • Client Scripting: Form Events & the Client API
  • Commands, Buttons & Custom Page Navigation
  • PCF Components: Build & Lifecycle
  • PCF Components: Package, Deploy & Advanced Features

Domain 5: Extend the Platform

  • The Plug-in Pipeline: How Dataverse Processes Events Free
  • Writing Plug-ins: Business Logic, Service & Registration
  • Custom APIs & Business Events
  • Custom Connectors: OpenAPI & Authentication
  • Custom Connectors: Azure, Policies & Code
  • Dataverse APIs: Web API & Organisation Service
  • Azure Functions for Power Platform
  • Cloud Flows: Dataverse Triggers & Expressions
  • Cloud Flows: Security, Errors & Child Flows

Domain 6: Develop Integrations

  • Publishing Dataverse Events
  • Service Endpoints: Webhooks, Service Bus & Event Hub
  • Data Sync: Change Tracking, Alternate Keys & Upsert
Domain 4: Extend the User Experience Premium ⏱ ~14 min read

Client Scripting: Form Events & the Client API

Add intelligence to model-driven app forms with JavaScript. Learn the Client API object model, form event handlers, and how to call the Dataverse Web API from client scripts.

Adding brains to model-driven forms

☕ Simple explanation

Think of a smart home system.

Without automation, you manually turn lights on, adjust the thermostat, and lock the doors. With a smart system, things happen automatically: motion sensor triggers lights, temperature drops trigger heating, and the door locks when you leave.

Client scripts are the smart system for model-driven app forms. When a user opens a form (OnLoad), changes a field (OnChange), or saves a record (OnSave) — your JavaScript responds automatically. You can show or hide fields, set values, validate data, display notifications, and even call external APIs.

Client scripting in model-driven apps uses JavaScript to extend form behaviour through the Client API object model. The Client API provides programmatic access to form controls, fields, tabs, sections, navigation, and the Dataverse Web API.

Scripts are stored as web resources (JavaScript files uploaded to Dataverse) and are registered to form events through the form designer. The modern pattern uses formContext (received via the execution context) instead of the deprecated Xrm.Page.

The exam tests your ability to write event handlers, interact with form controls, call the Web API from scripts, and understand the execution context — particularly the difference between the execution context (event metadata) and the form context (form control access).

The Client API object model

The Client API gives you access to everything on the form:

ObjectAccess ViaWhat It Controls
formContextexecutionContext.getFormContext()The form itself — all controls, fields, tabs
formContext.data.entityForm dataField values, save state, entity name
formContext.uiForm UITabs, sections, controls, notifications
formContext.getAttribute(“name”)Specific fieldGet/set value, add onChange handler
formContext.getControl(“name”)Specific controlShow/hide, enable/disable, set label
Xrm.NavigationGlobalOpen forms, dialogs, web resources
Xrm.WebApiGlobalCRUD operations on Dataverse tables
Xrm.UtilityGlobalShow progress indicator, get entity metadata

The formContext pattern

Every event handler receives an execution context. From that, you get the form context:

// Modern pattern — ALWAYS use this
function onFormLoad(executionContext) {
    var formContext = executionContext.getFormContext();
    
    // Read a field value
    var priority = formContext.getAttribute("priority").getValue();
    
    // Show/hide a control
    if (priority === 1) {
        formContext.getControl("escalation_notes").setVisible(true);
    }
    
    // Set a field as required
    formContext.getAttribute("description").setRequiredLevel("required");
    
    // Display a notification
    formContext.ui.setFormNotification(
        "This is a high-priority case", "WARNING", "priority_warning"
    );
}
💡 Exam tip: Xrm.Page is deprecated

If you see Xrm.Page.getAttribute(...) in an exam answer, it is almost certainly wrong. The modern approach is:

  1. Receive executionContext as a parameter
  2. Call executionContext.getFormContext() to get formContext
  3. Use formContext for all form operations

Xrm.Page still works (backwards compatibility) but is deprecated and does not support multi-session apps where multiple forms can be open simultaneously.

Event handler registration

Event handlers connect your JavaScript functions to form events. There are two ways to register them:

Register in the form designer unless you have a specific reason not to
MethodForm Designer (Recommended)Programmatic (addOnChange)
HowConfigure in the form editor UI under Events tabCall formContext.getAttribute('field').addOnChange(handler) in code
Visible to makersYes — shows in form propertiesNo — hidden in JavaScript
Solution-awareYes — travels with the form customisationDepends on when/where the code runs
Best forOnLoad, OnSave, field OnChange events you always wantDynamic handlers added conditionally at runtime
Exam preferenceAlmost always correctCorrect only when dynamic registration is needed

Calling the Dataverse Web API from scripts

The Xrm.WebApi object lets you perform CRUD operations from client scripts without leaving the form:

// Read a related record
function loadAccountDetails(formContext) {
    var accountRef = formContext.getAttribute("parentaccountid").getValue()[0];
    var accountId = accountRef.id.replace(/[{}]/g, ""); // Strip braces from GUID
    
    Xrm.WebApi.retrieveRecord("account", accountId, 
        "?$select=name,revenue,numberofemployees"
    ).then(
        function(result) {
            // Use the data
            formContext.getControl("account_info").setLabel(
                result.name + " - Revenue: $" + result.revenue
            );
        },
        function(error) {
            console.error("Error: " + error.message);
        }
    );
}

// Create a related record
function createFollowUpTask(formContext) {
    var caseId = formContext.data.entity.getId();
    var record = {
        subject: "Follow up on case",
        "regardingobjectid_incident@odata.bind": "/incidents(" + caseId + ")",
        scheduledend: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days from now
    };
    
    Xrm.WebApi.createRecord("task", record).then(
        function(result) {
            formContext.ui.setFormNotification(
                "Follow-up task created", "INFO", "task_created"
            );
        },
        function(error) {
            formContext.ui.setFormNotification(
                "Error creating task: " + error.message, "ERROR", "task_error"
            );
        }
    );
}
💡 Scenario: Kai adds smart form behaviour

Kai is building a shipment form at LogiFlow. When the destination country changes:

  1. OnChange handler fires on the destinationcountry field
  2. Script calls Xrm.WebApi.retrieveMultipleRecords() to fetch customs requirements for that country
  3. If the country requires customs documentation, the script shows the “Customs Documents” tab and sets the “Customs Declaration” field as required
  4. If the country is domestic, the script hides the tab and clears the requirement

This logic is registered through the form designer (OnChange on destinationcountry) and uses formContext for all form interactions. The Web API call is async — the form remains responsive while data loads.

Question

What is the execution context in client scripting?

Click or press Enter to reveal answer

Answer

The execution context is an object passed to every event handler function. It contains metadata about the event (which field changed, save mode, etc.) and provides getFormContext() to access the form. Always pass execution context as the first parameter and check 'Pass execution context' in the form designer.

Click to flip back

Question

How do you show a notification on a model-driven app form using JavaScript?

Click or press Enter to reveal answer

Answer

Use formContext.ui.setFormNotification(message, level, uniqueId). Levels: 'ERROR' (red), 'WARNING' (yellow), 'INFO' (blue). The uniqueId lets you clear the notification later with formContext.ui.clearFormNotification(uniqueId).

Click to flip back

Question

What is the difference between getAttribute and getControl in the Client API?

Click or press Enter to reveal answer

Answer

getAttribute('name') returns the data attribute — use it to get/set field values, add OnChange handlers, and check required level. getControl('name') returns the UI control — use it to show/hide, enable/disable, set labels, and manage focus. Same field, different access points.

Click to flip back

Knowledge Check

Kai registers an OnLoad handler on a model-driven form. The handler should read the Priority field and conditionally show a tab. Which code pattern is correct?

🎬 Video coming soon

Next up: Commands, Buttons & Custom Page Navigation — customising the command bar with Power Fx and JavaScript.

← Previous

Troubleshoot & Optimise Apps

Next →

Commands, Buttons & Custom Page Navigation

Guided

I learn, I simplify, I share.

A Guide to Cloud YouTube Feedback

© 2026 Sutheesh. All rights reserved.

Guided is an independent study resource and is not affiliated with, endorsed by, or officially connected to Microsoft. Microsoft, Azure, and related trademarks are property of Microsoft Corporation. Always verify information against Microsoft Learn.