You are here:
Runtime Changes and Interactions
The communication between a UI contract and a UIPluginV2 happens using Bindings and Events.
Required Editions
| Available in: Enterprise, Performance, and Unlimited Editions that have Consumer Goods Cloud enabled |
Properties to fetch bindings or framework functions such as FWThrowEvent aren’t available in this plugin. To solve this issue, an instance of
JS (JavaScript) object PluginManager is added to a hidden script tag in all plugins. The JS
object facilitates the communication between UIPluginV2 and the application framework.
Here’s a run-time representation of UIPluginV2
- Bindings
- A PluginManager contains Bindings as attributes. For two-way bindings, updating this
attribute updates the corresponding binding in a contract, whereas updating a one-way
binding attribute doesn't do so.
For example, if a binding is named Title, then you can fetch it by
PluginManager.Title.<UIDescription name="FWUIPluginV2::ShowPluginUI" schemaVersion="0.0.0.5"> <Page pagePattern="SingleSectionPage"> <PageHeader> <Bindings> <Resource target="title" type="Label" id="TitleId" defaultLabel="UIPluginV2" bindingMode="ONE_TIME" /> </Bindings> </PageHeader> <Section sectionName="masterSection" sectionPattern="SingleAreaSection"> <Area areaName="mainArea" areaPattern="SingleElementArea"> <UIPluginV2 name="MyTestUIPluginV2"> <Bindings> <Binding target="Title" type="Text" id="NewTitleId" binding="ProcessContext::testPlugin.title" defaultLabel="SenderTitle" bindingMode="TWO_WAY" /> </Bindings> </UIPluginV2> </Area> </Section> </Page> </UIDescription>Similarly,
PluginManager.Title = "Name"updates the corresponding binding.<UIPluginV2 name="MyTestUIPluginV2" mainComponent="main"> <Interface> <Property id="Title" /> </Interface> <Libraries/> <UIComponentHTML name="TestHTML"> <![CDATA[ <p id="titleText">Default Title</p> <label for="titleId">Change Title by Bindings</label><br><br> <input type="text" id="titleId" name="ChangeTitleUsingBindings"><br><br><br> ]]> </UIComponentHTML> <UIComponentCSS name="TestCSS"> <![CDATA[ .buttonClass { min-width: 50px; min-height:50px } ]]> </UIComponentCSS> <UIComponentJS name="TestJS"> <![CDATA[ document.body.addEventListener('input', function (e) { if(e.target.id === "titleId") { // Whenever input changes, the two-way binding Title would change and thereby changing "ProcessContext::testPlugin.title" PluginManager.Title=event.target.value; } }); ]]> </UIComponentJS> </UIPluginV2> - Events
- PluginManager contains a method,
throwEventto call the corresponding action defined in the contract. ThethrowEventmethod accepts two attributes,eventNameandeventParams.For example,
PluginManager.throwEvent("updateReceiverTitle",{id : "00x"});Parameters used for Events: PluginManager.throwEvent(name, params)
namemust be of type string and be the same name as in UI contract.paramsmust be of type object and all of its attributes must be declared in the contract.
Here’s a sample UIDescription and UI contract.
<UIDescription name="FWUIPluginV2::ShowPluginUI" schemaVersion="0.0.0.5">
<Page pagePattern="SingleSectionPage">
<PageHeader>
<Bindings>
<Resource target="title" type="Label" id="TitleId" defaultLabel="UIPluginV2" bindingMode="ONE_TIME" />
</Bindings>
</PageHeader>
<Section sectionName="masterSection" sectionPattern="SingleAreaSection">
<Area areaName="mainArea" areaPattern="SingleElementArea">
<UIPluginV2 name="MyTestUIPluginV2">
<Bindings>
<Binding target="Title" type="Text" id="NewTitleId" binding="ProcessContext::testPlugin.title" defaultLabel="SenderTitle" bindingMode="TWO_WAY" />
</Bindings>
<Events>
<CustomPluginEvent name="updateReceiverTitle" event="updateReceiverTitleEvent">
<Params>
<Param name="title" value=".title" />
</Params>
</CustomPluginEvent>
</Events>
</UIPluginV2>
</Area>
</Section>
</Page>
</UIDescription><UIPluginV2 name="MyTestUIPluginV2" mainComponent="main">
<Interface>
<Property id="Title" />
<Events>
<Event name="updateReceiverTitle" />
</Events>
</Interface>
<Libraries/>
<UIComponentHTML name="TestHTML">
<![CDATA[
<p id="titleText">Default Title</p>
<label for="titleId">Change Title by Events</label><br><br>
<input type="text" id="titleId" name="ChangeTitleUsingEvents"><br><br><br>
]]>
</UIComponentHTML>
<UIComponentCSS name="TestCSS">
<![CDATA[
.buttonClass {
min-width: 50px;
min-height:50px
}
]]>
</UIComponentCSS>
<UIComponentJS name="TestJS">
<![CDATA[
document.body.addEventListener('input', function (e) {
if(e.target.id === "titleId") {
// Whenever input changes, this event would be fired and corresponding logic in contract would be triggered
PluginManager.throwEvent("updateReceiverTitle",{
title : event.target.value
});
}
});
]]>
</UIComponentJS>
</UIPluginV2>The lifecycle of a UIPluginV2 includes:
- ConnectCallback
- RenderCallback
- DisconnectCallback
- Debugging UI plugin code
- ConnectCallback
-
When the UI plugin is loaded and PluginManager is available, the system invokes the
connectCallbackmethod. You can use this method to initialize the plugin.For example, if the UI required a resource binding,
Title, you can use this callback to update the UI during initialization.<UIDescription name="FWUIPluginV2::ShowPluginUI" schemaVersion="0.0.0.5"> <Page pagePattern="SingleSectionPage"> <PageHeader> <Bindings> <Resource target="title" type="Label" id="TitleId" defaultLabel="UIPluginV2" bindingMode="ONE_WAY" /> </Bindings> </PageHeader> <Section sectionName="masterSection" sectionPattern="SingleAreaSection"> <Area areaName="mainArea" areaPattern="SingleElementArea"> <UIPluginV2 name="MyTestUIPluginV2"> <Bindings> <Resource target="Title" type="Label" id="TitleId" defaultLabel="UIPluginV2" bindingMode="ONE_WAY" /> </Bindings> </UIPluginV2> </Area> </Section> </Page> </UIDescription><UIPluginV2 name="MyTestUIPluginV2" mainComponent="main"> <Interface> <Property id="Title" /> <Property id="SubTitle" /> </Interface> <Libraries/> <UIComponentHTML name="TestHTML"> <![CDATA[ <p id="titleText">Default Title</p> ]]> </UIComponentHTML> <UIComponentCSS name="TestCSS"> <![CDATA[ .buttonClass { min-width: 50px; min-height:50px } ]]> </UIComponentCSS> <UIComponentJS name="TestJS"> <![CDATA[ function connectCallback() { document.getElementById('titleText').innerHTML = PluginManager.Title; // Some initialization tasks } ]]> </UIComponentJS> </UIPluginV2> - RenderCallback
-
The system calls this method whenever the parent component is re-rendered. You can use this callback as a listener to any binding updates or orientation changes.
For example, if changes in SubTitle binding are required in the UI, you can use this callback to update the UI for every change.
<UIDescription name="FWUIPluginV2::ShowPluginUI" schemaVersion="0.0.0.5"> <Page pagePattern="SingleSectionPage"> <PageHeader> <Bindings> <Resource target="title" type="Label" id="TitleId" defaultLabel="UIPluginV2" bindingMode="ONE_WAY" /> </Bindings> </PageHeader> <Section sectionName="masterSection" sectionPattern="SingleAreaSection"> <Area areaName="mainArea" areaPattern="SingleElementArea"> <UIPluginV2 name="MyTestUIPluginV2"> <Bindings> <Resource target="title" type="Label" id="TitleId" defaultLabel="UIPluginV2" bindingMode="ONE_WAY" /> <Binding target="SubTitle" type="Text" id="SubTitleId" binding="ProcessContext::testPlugin.subTitle" defaultLabel="SenderSubTitle" bindingMode="TWO_WAY" /> </Bindings> </UIPluginV2> </Area> </Section> </Page> </UIDescription><UIPluginV2 name="MyTestUIPluginV2" mainComponent="main"> <Interface> <Property id="Title" /> <Property id="SubTitle" /> </Interface> <Libraries/> <UIComponentHTML name="TestHTML"> <![CDATA[ <p> Sender </p> <p id="titleText">Default Title</p> <p id="subTitleText">Default SubTitle</p> ]]> </UIComponentHTML> <UIComponentCSS name="TestCSS"> <![CDATA[ .buttonClass { min-width: 50px; min-height:50px } ]]> </UIComponentCSS> <UIComponentJS name="TestJS"> <![CDATA[ function connectCallback() { document.getElementById('titleText').innerHTML = PluginManager.Title; // Some initialization tasks } function renderCallback() { // Whenever binding of SubTitle changes, renderCallback is triggered and UI will be updated document.getElementById('subTitleText').innerHTML = PluginManager.SubTitle; } ]]> </UIComponentJS> </UIPluginV2> - DisconnectCallback
-
You can use this callback method to clean up the plugin just before unmounting. For example, if a plugin is on a UI screen that contains a page header with a Back button, then this method is invoked when you click Back.
Limitations of the DisconnectCallback method are:
- If you use this callback method with
throwEventsor to update any bindings of the current UI process, such requests are ignored. - These callbacks time out and therefore can't contain any async calls or large processes.
- If there are multiple plugins in the current screen to unmount, the system calls the disconnectCallback method for all the plugins in no specific order. Also, the time-out is applied on all these callbacks.
<UIComponentJS name="TestJS"> <![CDATA[ this.timeoutID = setTimeout(() => {}, 1000); function disconnectCallback() { // Clean up any open processes clearTimeout(this.timeoutId); } ]]> </UIComponentJS> - If you use this callback method with
- Debugging UI plugin code
- The source URL of JS code in UIPlugin is mapped to UIPluginV2_PluginName. This name can be used in dev tools to debug the plugin code. For example, for a UIPlugin named TestUIPlugin, search UIPluginV2_TestUIPlugin to get the JS code.

