Tuesday 14 September 2021

Dynamic Interactions in Winter 22

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);
        }
    }

and the final step is to use the Lightning App Builder to define what happens when the accountSelected event fires. I edit the page and click on the chooseAccount component, and there's a new tab next to the (lack of) properties that allows me to define interactions for the component - the Account Selected event:


and I can then fill in the details of the interaction:


In this case I'm targeting the accountInfo component and setting its public properties recordId and recordName to their namesakes from the published event. If I had additional components which cared about an account being selected, I'd create additional interactions to change their state to reflect the selection.

I now have two components communicating with each other, without either of them knowing anything about the other one, using entirely standard functionality. I can wire up additional components, move them around, or delete components at will.  

Conclusion


I regularly find myself producing is highly custom user interfaces that allow multiple records to be managed on a single page. For this use case, Dynamic Interactions are nothing short of a game changer, and I'm certain that this will be my go to solution. 

Related




2 comments:

  1. recordId, recordName are mandatory parameters always? Because if I change the recordId, recordName names to something else in listener it gives compile time error.

    ReplyDelete
  2. They 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