Tweet |
Introduction
If all goes according to plan, Dynamic Interactions go GA in Winter 22. The release notes have this to say about them:
With Dynamic Interactions, an event occurring in one component on a Lightning page, such as the user clicking an item in a list view, can update other components on the page.
Which I think is very much underselling it, as I'll attempt to explain in the rest of this post.
Sample App
You can find the code for the sample app at the Github repository. There's not a huge amount to it, you choose an Account and another component gets the Id and Name of the Account and retrieves the Opportunities associated with it:
Component Decoupling
What Dynamic Interactions actually allow us to do is assemble disparate components into custom user interfaces while retaining full control over the layout. The components can come from different developers, and we can add or remove components that interact with each other without having to update any source code, or with the components having the faintest idea about what else is on the page.
This is something I've wanted for years, but was never able to find a solution that didn't require my custom components to know something about what was happening on the page.
The original way of providing a user with components that interact with each other was to create a container component and embed the others inside it. The container knows exactly which components are embedded, and often owns the data that the other components work on. There's no decoupling, and no opportunity to change the layout as you get the container plus all it's children or nothing.
Lightning Message Service was the previous game changer, and that allowed components to be fairly loosely coupled. They would publish events when something happened to them, and receive events when something happened elsewhere that they needed to act on. They were still coupled through the messages that were sent and received though - any component that wished to participate had to know about the message channels that were in use and make sure they subscribed to and published on those. Good luck taking components developed by a third party and dropping those in to enhance your page. It did allow the layout to be easily changed and components, as long as they knew about the channels and messages, to be added and removed without changing any code. I was planning a blog post on this, but masterful inactivity has once again saved me the trouble of writing it then having to produce another post recommending against that approach
With Dynamic Interactions, all that needs to happen is that components publish events when things of interest happen to them, and expose public properties that can be updated when things they should be interested in happen, the dream of decoupled components is realised. The components don't have to listen for each other's events, that is handled by the lightning app builder page. As the designer of the page, I decide what should happen when a specific component fires a particular event fires. Essentially I use the page builder to wire the components to each other, through configuration.
Back to the Sample App
My app consists of two components (no container needed):
-
chooseAccount - this retrieves all the accounts in the system and presents
the user with a lightning-combobox so they can pick one. In the screenshot
above, it's on the left hand side. When the user chooses an account, an
accountselected CustomEvent is fired with the details - all standard LWC:
this.dispatchEvent( new CustomEvent( 'accountselected', {detail: { recordId: this.selectedAccountId, recordName: this.selectedAccountName } }) );
- accountInfo - this retrieves the opportunity information for the recordId that is exposed as a public property, again all standard and, thanks to reactive properties, I don't have to manually take action when the id changes:
@api get recordId() { return this._recordId; } set recordId(value) { if (value) { this._recordId=value; this.hasAccount=true; } } .... @wire(GetOpportunitiesForAccount, {accountId: '$_recordId'}) gotOpportunities(result){ if (result.data) { this.opportunities=result.data; this.noOpportunitiesFound=(0==this.opportunities.length); } }
recordId, recordName are mandatory parameters always? Because if I change the recordId, recordName names to something else in listener it gives compile time error.
ReplyDeleteThey aren’t mandatory, but you’d need to change them everywhere to use different names and I don’t know if the interaction confit allows you to update.
ReplyDelete