Designing UX Components: Canvas, PCF & Client Scripts
Power Platform offers three ways to build custom user experiences. Learn when to choose canvas components, PCF code components, or client scripts β and how to design them for reuse across solutions.
Three paths to custom UX
Think of three types of car customisation.
Canvas components are like bolt-on accessories β a new steering wheel cover, custom floor mats. Anyone can install them, they are easy to swap, but they only work inside canvas apps.
PCF code components are like a custom engine modification. They require a mechanic (developer) with TypeScript skills, but they work in both canvas and model-driven apps β and they can do things no standard part can do.
Client scripts are like rewiring the dashboard electronics. JavaScript code that runs inside model-driven apps, controlling form behaviour, field visibility, and validation. Powerful but specific to model-driven forms.
The exam tests whether you pick the right customisation approach for each scenario.
Decision matrix: Which component type?
| Factor | Canvas Component | PCF Code Component | Client Script |
|---|---|---|---|
| Language | Power Fx (no-code) | TypeScript + React | JavaScript |
| Runs in | Canvas apps only | Canvas + model-driven apps | Model-driven apps only |
| Skill level | Maker (citizen developer) | Pro developer | Pro developer |
| Reusability | Component library (canvas) | Solution package (any app) | Web resource (model-driven) |
| External APIs | Via connectors in the host app | Via Web API feature in PCF | Via Xrm.WebApi or fetch |
| Access to device | Limited (camera via control) | Device API (camera, location, barcode) | No |
| Custom rendering | Power Fx layout only | Full HTML/CSS/React rendering | DOM manipulation (fragile) |
| Best for | Reusable form sections, branded inputs | Rich visualisations, custom grids, maps | Form logic, field visibility, validation |
Quick decision flow
Ask these questions in order:
- Does it need to work in a model-driven app? β If yes, use PCF or client script (not canvas component)
- Is it purely form logic (show/hide, validate, set values)? β Client script
- Does it need custom visual rendering? β PCF code component
- Is it a reusable form section for canvas apps only? β Canvas component
- Does it need device access (camera, GPS)? β PCF code component (Device API)
Scenario: Marcus chooses the right component
Marcus Chen is an ISV developer at NovaSoft Solutions. He is building a product catalogue app that will be sold on AppSource. The catalogue needs:
- A custom star-rating control that works in both canvas and model-driven apps β PCF component β needs to work cross-app and needs custom rendering
- A branded header section reused across 5 canvas apps β Canvas component library β canvas-only, reusable across apps, no code needed
- Auto-populate a βRegionβ field when the user selects a country on a model-driven form β Client script β form-level logic in model-driven app, no custom rendering needed
Each requirement maps to a different component type based on where it runs and what it does.
Designing for reuse
The best components are built once and used many times. Here are design principles for each type:
Canvas components
- Use custom properties β input properties for configuration, output properties for data, function properties for callbacks
- Keep components stateless where possible β pass data in, emit events out
- Component libraries let you share components across multiple canvas apps in the same environment
- Version carefully β updating a library component updates all apps that use it
PCF code components
- Design the manifest first β the
ControlManifest.Input.xmldefines what data the component accepts and returns - Field vs dataset binding β field components bind to a single column; dataset components bind to a view or collection
- Package as a solution β PCF components travel in Dataverse solutions for ALM
- Avoid tight coupling β donβt hardcode table names or column names; use the manifest to accept them as parameters
Client scripts
- One web resource per feature area β donβt put all scripts in one massive file
- Use the formContext pattern β never use the deprecated
Xrm.Page; always receiveexecutionContextand callgetFormContext() - Register event handlers through the form designer β not in code (makes them visible to other makers)
- Namespace your functions β
NovaSoft.Claims.onLoad()notonLoad()to avoid conflicts
Marcus needs to build a barcode scanner control that works in both canvas apps and model-driven apps. The control should open the device camera, scan a barcode, and return the scanned value to the form field. Which approach should he use?
A consulting team needs to add form validation to a model-driven app: when the Priority field changes to 'Critical', the Description field must become required and a notification banner must appear. Which approach is most appropriate?
π¬ Video coming soon
Next up: Designing Platform Extensions β custom connectors, plug-ins, custom APIs, and Power Fx functions.