Passing Data Between Freedom UI Pages in Creatio (Real Project Case)
Introduction
This article is based on a real Freedom UI use case, not a hypothetical demo.
The requirement comes from an actual configuration scenario:
- A Freedom UI form page (
UsrSmartFilter_FormPage) - A custom Freedom UI component/page (
UsrColumnViewerComponent) - The need to pass runtime values (object name + record Id)
- And then persist user selections back into the database
No sandbox. No assumptions. Only what works in Freedom UI today.
Real Problem Statement
In a Freedom UI implementation, the user:
- Opens UsrSmartFilter_FormPage
- Selects an object (for example:
Account,Contact, etc.) - Clicks a button to configure columns
- A second Freedom UI page/component opens
- That page must:
- Know which object was selected
- Know which UsrSmartFilter record is being edited
- Show all columns of the selected object
- Save selected column names back to
UsrSmartFilter.UsrColumnNames_Values
Classic UI sandbox messaging cannot be used.
Why Sandbox and Page Parameters Cannot Be Used
In Freedom UI:
- Pages are isolated
- There is no exposed sandbox API
- Parameters passed via
crt.OpenPageRequestare not injected into the target page context
This is a documented and observed platform behavior, not a theory.
The Working Mechanism: BroadcastChannel
The solution that works reliably is using the browser-native <strong>BroadcastChannel</strong> API.
This is not a Creatio abstraction. It is a standard Web API that works because:
- Freedom UI pages run in the same browser context
- Messaging happens at the browser level
- No Creatio internals are bypassed
Real Sender: UsrSmartFilter_FormPage Handler
This handler exists on UsrSmartFilter_FormPage and is triggered by a button click.
What It Sends
- Selected object schema name
- Current page record Id (
UsrSmartFilter.Id)
Real Handler Code
{ request: "QNT.GetColumns", handler: async (request, next) => { const objectValue = request.$context.PDS_UsrSelectedObject_n4di2v4; const pageId = request.$context.Id; if (!objectValue || !pageId) { return next?.handle(request); } const channel = new BroadcastChannel("UsrSmartFilter_Channel"); channel.postMessage({ selectedObjectName: objectValue.displayValue, pageId: pageId }); channel.close(); return next?.handle(request); } }
This code is taken directly from a working Freedom UI page.
Real Receiver: UsrColumnViewerComponent
UsrColumnViewerComponent is a custom Freedom UI component responsible for:
- Receiving the object name and page Id
- Loading the selected object schema dynamically
- Allowing the user to select columns
- Persisting the selection
Receiving the Data
this._channelIn = new BroadcastChannel("UsrSmartFilter_Channel"); this._channelIn.onmessage = async (event) => { const { selectedObjectName, pageId } = event.data || {}; this._selectedObjectName = selectedObjectName; this._parentPageId = pageId; await this._loadObjectSchema(); this._render(); };
This logic runs when the component is initialized.
Loading the Object Schema Dynamically
Instead of hardcoding Account, the schema is loaded dynamically using the received object name:
const model = await sdk.Model.create(this._selectedObjectName); const schema = await model.getSchema(); this._columns = Object.values(schema.attributes).map(attr => ({ name: attr.name, caption: attr.caption || attr.name }));
This is standard Freedom UI Model API usage.
Persisting the Selected Columns (Real Persistence)
When the user selects or unselects columns, the component:
- Builds a comma-separated string
- Updates the existing
UsrSmartFilterrecord
const model = await sdk.Model.create("UsrSmartFilter"); await model.update({ Id: this._parentPageId, UsrColumnNames_Values: columnsCsv });
This is not messaging — this is actual data persistence.
Why This Is a Real, Production-Safe Pattern
- Uses only documented Web APIs
- Uses Creatio Freedom UI Model API
- No reliance on undocumented sandbox features
- Works across page reloads once persisted
This pattern has been validated in real projects.
Key Constraints (Real, Not Theoretical)
BroadcastChanneldoes not queue messages- Receiver must be initialized first
- Transient data should always be persisted
Ignoring these leads to real bugs.
Conclusion
This article does not describe a hypothetical demo.
It documents a real Freedom UI implementation pattern for:
- Passing data between pages
- Dynamically loading object metadata
- Persisting user configuration
Until Creatio provides an official sandbox replacement for Freedom UI, this is the correct approach.
Final Takeaway
Freedom UI pages do not share state.
Browser-level messaging + Model API persistence is the only reliable solution today.
This is based on actual working code, not assumptions.