Building an Iframe-Based Gallery Control in Power Apps (PCF)

 

Functional Overview

From a functional perspective, the control does three main things:

  1. Loads a web resource inside an iframe

  2. Sends data to the iframe to render a gallery

  3. Listens to user actions from the iframe and exposes them as outputs

What the User Sees

  • A gallery rendered inside an iframe

  • Data-driven columns and rows

  • Actions like:

    • Selecting records

    • Editing a single record

    • Deleting one or many records with a reason

    • Copying a record

All UI logic lives inside the iframe. The PCF control acts as a bridge between Power Apps and that UI.


Key Inputs and Outputs

Inputs (from Power Apps)

The control expects JSON-based inputs:

  • webResourceUrl – URL of the HTML/JS gallery

  • columnsJson – Column definitions

  • dataJson – Records to display

  • deleteReasonJson – Allowed delete reasons

These are passed as strings and parsed at runtime.

Outputs (to Power Apps)

The control exposes two outputs:

  • selectedRecordJson

  • actionType

Together, these tell Power Apps:

  • What the user did

  • Which records were affected

  • Any additional data (like delete reason)


Technical Architecture

PCF as a Message Broker

This control deliberately avoids rendering UI directly in PCF. Instead:

  • The PCF control hosts an iframe

  • Communication happens via postMessage

  • Data flows both ways

This keeps the PCF logic simple and lets the UI evolve independently.


Initialization Flow

init()

The init method sets up everything:

  • Stores context and callback

  • Creates the iframe

  • Loads the web resource URL

  • Registers a global message listener

this.iframe = document.createElement("iframe"); this.iframe.src = context.parameters.webResourceUrl?.raw ?? "";

Once the iframe loads, the control immediately sends initialization data.


Sending Data to the Iframe

sendDataToIframe()

This method prepares and sends data required by the gallery UI.

Steps:

  1. Parse JSON safely using try/catch

  2. Store delete reasons locally

  3. Send everything using postMessage

this.iframe.contentWindow?.postMessage( { type: "INIT_GALLERY", columns, data, deleteReasons }, "*" );

If invalid JSON is passed, the control fails gracefully and sends empty arrays.


Handling User Actions

handleIframeEvents()

This is the core interaction logic.

The iframe sends messages with a type and payload. The control listens and translates those into Power Apps outputs.

Supported actions:

Action TypeDescription
SELECTION_CHANGEMultiple record selection
EDITSingle record edit
DELETESingle delete with reason
BULK_DELETEMultiple deletes with reason
COPYCopy a record

Each case sets:

  • actionType

  • selectedRecordsJson

Then it calls:

this.notifyOutputChanged();

This tells Power Apps to re-evaluate formulas and react.


Output Structure Examples

Selection Change

[ { "id": "1" }, { "id": "2" } ]

Delete / Bulk Delete

{ "records": [{ "id": "1" }, { "id": "2" }], "reason": "Duplicate" }

Copy

[ { "requestId": "abc123" } ]

The format is intentionally flexible so Power Apps can branch logic easily.




Update and Lifecycle Handling

updateView()

Whenever inputs change (new data, refreshed view), the control:

  • Updates context

  • Re-sends data to the iframe

This keeps the UI in sync without reloading the iframe.

destroy()

The control cleans up properly by removing the event listener:

window.removeEventListener("message", this.handleIframeEvents);

This avoids memory leaks when navigating between screens.


Why This Pattern Works Well

This design offers several advantages:

  • Separation of concerns
    UI logic lives outside PCF.

  • Reusability
    The same iframe UI can be reused elsewhere.

  • Flexibility
    Complex UI frameworks can be used inside the iframe.

  • Simple PCF code
    The control focuses only on data flow and events.


Final Thoughts

This iframe-based PCF control is a solid pattern when you need rich, custom UI without fighting PCF rendering limits. By using postMessage, you get a clean contract between Power Apps and your UI layer.

Comments

Popular posts from this blog

Attachment PCF

Contacts View PCF Control

Trigger JavaScript on Click of Button PCF Control