Tutorials/Power Apps/Building Interactive Canvas Components with Custom Behaviors
Power Appsintermediate

Building Interactive Canvas Components with Custom Behaviors

Learn how to add OnConfirm and OnCancel behavior properties to your Power Apps components, eliminating workarounds and enabling true UI abstraction.

NA
Narmer Abader
@narmer · Published June 3, 2026

One of the most requested features for canvas app components was the ability to expose behaviors back to the host app. For years, developers had to hack around this limitation by writing global variables from inside a component or using collections to trigger events externally. The introduction of Behavior Properties (like OnSelect and OnChange) completely changed the game. Components finally became truly interactive units that could communicate their internal events cleanly.

In this guide, we will move past the old workarounds and build a reusable confirmation dialog. You will learn how to design a component's interface, wire up its behavior properties, and consume them in a real-world scenario without breaking encapsulation.

Why Behavior Properties Matter

Before enhanced component properties, if a button inside a component needed to perform an action in the app (like navigating or saving data), you had to resort to brittle patterns:

  • Global Variables: The component would Set(varAction, "confirm") while the app polled or observed this variable. This tightly coupled the component to the app's global state.
  • Collections: The component would Collect(EventQueue, {Action: "confirm"}) and the app would monitor the collection. Fragile and hard to debug.
  • Timer Controls: The component would start a timer in the app to simulate a delayed action. Inelegant and a source of timing bugs.

Behavior properties eliminate all of this. They act as a clean output channel. The component announces "the user clicked confirm, run whatever logic the app defines," and the host app independently provides that logic. This is the foundation of a healthy separation of concerns in Power Apps.

Our Scenario: A Reject Order Dialog

Imagine you are building a purchase order approval app. An approver sees a gallery of pending orders. Clicking a "Reject" button should display a confirmation dialog to prevent costly mistakes.

Component Name: cmp_ConfirmDialog

Input Properties (Data):

  • DialogTitle (Text): "Reject Order"
  • DialogMessage (Text): "Are you sure you want to reject order #ORD-0042?"
  • TargetRecord (Record): The specific order to reject.

Behavior Properties:

  • OnConfirm: Fires when the user clicks the Confirm button.
  • OnCancel: Fires when the user clicks the Cancel button.

App Variables:

  • _showConfirmDialog (Boolean): Controls the visibility of the component.
  • _confirmTarget (Record): Stores the record passed from the gallery.

Data Source: A SharePoint list or Dataverse table called Orders.

Step 1: Enable Enhanced Component Properties

Before creating the component, ensure the necessary feature toggle is active. Navigate to Settings -> Upcoming features -> Experimental and turn on Enhanced component properties.

Feature Availability

In newer environments this feature may already be graduated from experimental. Always verify your settings first.

Step 2: Design the Component

  1. Go to the Components tab in the Tree View.
  2. Insert a new component (New component). Rename it to cmp_ConfirmDialog.
  3. Add the following UI elements:
    • A Label for the title.
    • A Label for the message.
    • A Button labelled btnConfirm.
    • A Button labelled btnCancel.

Step 3: Create the Custom Behavior Properties

Open the Properties pane of the component.

  1. Create a new custom property:
    • Property name: OnConfirm
    • Property type: Behavior
    • Display name: OnConfirm
  2. Create a second custom property:
    • Property name: OnCancel
    • Property type: Behavior
    • Display name: OnCancel

Step 4: Wire the Buttons Inside the Component

This step is the core of the pattern. Inside the component, the button's OnSelect must explicitly invoke the component's behavior property. This exposes the event to the outside world.

For btnConfirm:

powerfxOnSelect of the Confirm button inside the component
cmp_ConfirmDialog.OnConfirm()

For btnCancel:

powerfxOnSelect of the Cancel button inside the component
cmp_ConfirmDialog.OnCancel()

The component is now complete. It has a clean output interface and knows exactly when to fire each event, but it is completely independent of the app's business logic.

Step 5: Consuming the Component in the App

Now we bring the component into the app and connect the real logic.

  1. Go to Screen 1 (or any screen).

  2. Insert a Gallery, bind it to the Orders data source.

  3. Add a Reject button inside the gallery template.

  4. On the Reject button's OnSelect, set the context variables to show the dialog and store the target record.

    powerfxOnSelect of the Gallery button
    UpdateContext({_showConfirmDialog: true, _confirmTarget: ThisItem})
  5. Insert the cmp_ConfirmDialog component onto the screen (from the Custom ribbon or Insert -> Custom).

  6. Set the component's input properties:

    • DialogTitle: "Confirm Rejection"
    • DialogMessage: "Are you sure you want to reject Order " & _confirmTarget.OrderID & "?"
    • TargetRecord: _confirmTarget
    • Visible: _showConfirmDialog
  7. Set the component's behavior properties:

    • OnConfirm:

      powerfxOnConfirm of the component instance
      Patch(Orders, _confirmTarget, {Status: "Rejected"}); UpdateContext({_showConfirmDialog: false})
    • OnCancel:

      powerfxOnCancel of the component instance
      UpdateContext({_showConfirmDialog: false})

Common Mistakes and Troubleshooting

  • "I can't see the behavior property in the property dropdown!" Verify that Enhanced Component Properties is turned on in Settings. Also confirm you created a custom property of type Behavior, not Data or Output.

  • "The code runs automatically when the screen loads!" This usually means you placed the cmp_ConfirmDialog.OnConfirm() call inside a property that evaluates immediately (like Visible or DisplayMode) rather than the OnSelect property of the button.

  • "My context variables aren't updating!" Context variables (UpdateContext) are scoped to the screen, not the component. You must define your OnConfirm and OnCancel formulas on the component instance in the app, not inside the component. The component should contain only the call to its own behavior property.

  • "I need to call OnConfirm conditionally inside the component!" You cannot call a behavior property from inside a function like If or Switch — they are imperative commands. If you need conditional logic inside the component (e.g., "if validation passes, fire OnConfirm"), expose multiple behavior properties and let the app handle the condition. Alternatively, set a data property to a validation result and drive the logic from the app side.

    Conditional Behavior Calls

    Behavior properties must be the direct result of a user action. You cannot nest them in conditionals inside the component. Keep the component simple and move complex decision logic to the app.

Security, Performance, and Delegation

Behavior properties themselves have no delegation issues, but the formulas you write inside the host app's event handlers must still follow standard Power Apps delegation rules. In the example above, Patch is delegable for most data sources. If you place a Filter inside an OnConfirm handler, ensure it can be delegated.

Using behavior properties encourages a clean architecture where the component is strictly a "view" and the host app handles all "controller" and "model" logic. This makes your code far easier to audit, test, and maintain over time.

Final Thoughts

Behavior properties are not a gimmick. They are the foundation for building professional, enterprise-grade canvas apps. By investing a few minutes to properly encapsulate a custom dialog inside a component with behavior outputs, you dramatically reduce duplication and complexity.

Go back to your existing apps and look for repetitive "Are you sure?" confirmation logic. Build a component for it. Your future self — and every developer who inherits your app — will thank you.


References