1

Basically I want to have two different LWCs in different columns in a flexible layout page. In one LWC will be two links- one link in LWC 1 will hide the contents of LWC 2 and the other link in LWC 1 will show the contents pf LWC 2 (In reality it will be a tabbed nav interface in one LWC hiding or showing the contents of several other LWCs, but the basic concept is, how to have one LWC affect another that is not a child).

I found this link that describes how to communicate between a parent and a child LWC, but that's not what I need. The 'instant communication' aspect, yes, but not the parent/child relationship.

I found this link that describes the Lightning Message Service, which looks promising, but it seems like, in addition to making the change in LWC 1 that should be communicated to LWC 2, there also needs to be an extra 'Publish' step in LWC 1 and a 'Subscribe' step in LWC 2. If there's a way to implement the Lightning Message Service instantly without clicking 'Publish' and 'Subscribe' buttons, as in the animated demo at the bottom of that link, I might be able to make this work.

It seems like this is much more difficult to find an answer to than it needs to be. Am I missing a simple way to do what I want-- take an action in LWC 1 that instantly affects LWC 2 without the need for an extra step?

0

2 Answers 2

0

There are several ways that LWCs can be written to communicate with each other. You have already referenced the first two I list below, but I outline all the options I am aware of here:

  • Standard event/API interactions, where the parent sends data to the child using API properties or functions on the child and the child sends data to the parent using (custom) events.
  • Lightning Messaging Service, where events are published on a channel by one LWC (or, indeed, other code) and another LWC (or other code) registers interest in receiving those events and has the events delivered after they are published.
  • Dynamic Interactions, where you write an LWC to act as a source of interaction messages and have these messages set up in the Lightning page to update one or more target components. Note that this is not supported in Digital Experiences at the moment (Spring '24).
  • Specifically in the context of screen flows, Reactive Components, where you write your LWC so it can notify the flow engine of an attribute change (using an output API property - these must be written using getter/setter pattern so the component is able to modify its own API property - and the FlowAttributeChange event. When you put the component in the flow, you connect its output API property to a variable and use that variable as the input for the other LWC's relevant API property, so the change in the first LWC propagates to the second one immediately, without the need for navigating between screens.

It is worth considering relying on the latter in many cases since screen flows can be embedded in Lightning and Digital Experience pages, as well as used as quick actions etc. This also means you can also make use of standard components (plus third party ones) to provide parts of the UX without having to develop so much of your own code.

0

Re the OP, you can use LMS for what you described, but as Phil says, Flow + LWC is probably easier. But as a simple POC, this will pass content from one LWC to a sibling via LMS: First, create a messageChannel via your IDE - in this case the meta file is file is called messageDemo.messageChannel:

<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <description>Enable LWC to pass messages to siblings</description>
    <isExposed>true</isExposed>
    <masterLabel>MessageDemo</masterLabel>
</LightningMessageChannel>

Them in your source LWC, setup the publishing and in this case, a simple input to trigger a publish change:

<template>
    <lightning-input value={vmessage} onchange={handleChange} label="Message Test"></lightning-input>
</template>

//Controller

import {LightningElement, api} from 'lwc';
import { createMessageContext, releaseMessageContext,publish } from 'lightning/messageService';
import messageDemoMC from "@salesforce/messageChannel/messageDemo__c";
export default class BfcSourceComponent extends LightningElement {

    context = createMessageContext();
    vmessage;

    publishMC() {
        console.log('publish')
        let payload = {};
        payload.msg = this.vmessage;
        try {
            publish(this.context, messageDemoMC, payload);
        }
        catch (e) {
            console.log(e.body.message);
        }
    }

    handleChange(event) {
        this.vmessage = event.target.value;
        this.publishMC();
    }
}

And then in the target, subscribe to the same channel and we can expose a variable that shows the payload from source:

<template>
    Target: {msg}
</template>

//Controller

import {LightningElement,wire} from 'lwc';
// Import message service features required for subscribing and the message channel
import {
    subscribe,
    unsubscribe,
    APPLICATION_SCOPE,
    MessageContext,
} from "lightning/messageService";
import messageDemoMC from "@salesforce/messageChannel/messageDemo__c";

export default class BfcTargetComponent extends LightningElement {
    msg;
    @wire(MessageContext)
    messageContext;

    connectedCallback() {
        this.subscribeToMessageChannel();
    }

    disconnectedCallback() {
        this.unsubscribeToMessageChannel();
    }

    subscribeToMessageChannel() {
        if (!this.subscription) {
            this.subscription = subscribe(
                this.messageContext,
                messageDemoMC,
                (message) => this.handleMessage(message),
                {scope: APPLICATION_SCOPE},
            );
        }
    }

    unsubscribeToMessageChannel() {
        unsubscribe(this.subscription);
        this.subscription = null;
    }

    handleMessage(message) {
        this.msg = message.msg;
        console.log('this.msg' + this.msg);
    }

}

enter image description here

2
  • BritishBoyinDC, Thanks, I followed your code example and got it to work. But, though this is probably blindingly simple, how do I extend this to other interactions-- such as a simple show / hide toggle command? Within a LWC I would have if:true={istestInfoVisible} Set for the block of HTML I want to show or hide. Then is the js: @track istestInfoVisible = true; Then I'd call a function in an onclick testToggleClick() { this.istestInfoVisible = !this.istestInfoVisible; How would I communicate that via Lightning Message Channel?
    – Mike
    Jan 16 at 20:24
  • The payload can be anything - so here is a similar example, but using a toggle in the source cmp make a section in the target show\hide gist.github.com/britishboyindc/8989275bb6d6b5cd9cfb57322db93982 Jan 17 at 12:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .