LWCで別のDOMツリーのコンポーネントに情報伝達する【Salesforce】

snowy terrain against green trees Lightning Web Component
Photo by Syed Andrabi on Pexels.com

Lightning Web Component でコンポーネント間の情報伝達をする際、コンポーネント同士が親子関係であれば、@api を使ったプロパティの受け渡しと、イベントの受け渡しで情報伝達をすることができます。

しかし、DOMツリーが異なるコンポーネントに対しては別のアプローチが必要です。
今回はLightning Message Service を使った情報伝達を紹介します。

Lightning Message Serviceを使った情報伝達

Lightning Message Service とは、出版-購読型モデルを使ったメッセージ伝達を行う機能です。

メッセージを発信する側は、チャネルを通してメッセージを発信します。出版-購読型モデルでは、発信側はメッセージの送り先を指定しません。

これは YouTuber が自分のチャンネルで動画を公開するようなものです。YouTube はメールなどと違って特定の受信者がいるわけではなく、不特定多数の人が動画を見ることができますよね。

一方、受信側は受信したいチャネルを指定することで、そのチャネルからメッセージが発信されるたびにメッセージを受け取ることができます。

YouTube の例えだと、特定のチャンネルについて動画公開時に通知を受けるような感じです。

実装例

publisherコンポーネントで発信したメッセージを、subscriberコンポーネントで受信して値を処理します。

まずはじめに、チャネルを作成します。

<?xml version="1.0" encoding="UTF-8" ?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <isExposed>true</isExposed>
    <masterLabel>Test Channel</masterLabel>
</LightningMessageChannel>

メッセージを発信するコンポーネントで先ほど作成したチャネルをインポートします。
messageService もインポートしてLMSの機能を使える様にします。

メッセージを発信する時は、publishメソッドを使います。
引数は順にコンポーネントの情報、チャネルの情報、受け渡すメッセージの内容、を指定しています。

import testMC from '@salesforce/messageChannel/TestChannel__c';
import { MessageContext, publish } from 'lightning/messageService';
import { LightningElement, wire } from 'lwc';

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

    // Respond to UI event by publishing message
    handleClick() {
        const payload = { value: 'aaa' };
        publish(this.messageContext, testMC, payload);
    }
}

メッセージを受信するコンポーネントでも、作成したチャネルと messageService をインポートします。

次に、subscribe メソッドを使って受信情報についてのインスタンスを作成します。このインスタンスが存在する限り、コンポーネントはメッセージを受信します。
subscribe メソッドの引数は順にコンポーネントの情報、チャネルの情報、メッセージ受信時に走るメソッド、メッセージを受信する範囲、を指定します。

import testMC from '@salesforce/messageChannel/TestChannel__c';
import {
    APPLICATION_SCOPE,
    MessageContext,
    subscribe,
    unsubscribe
} from 'lightning/messageService';
import { LightningElement, wire } from 'lwc';

export default class Subscriber extends LightningElement {
    catchEvent = false;
    subscription = null;
    _value;

    @wire(MessageContext)
    messageContext;

    connectedCallback() {
        this.subscribeToMessageChannel();
    }
    disconnectedCallback() {
        this.unsubscribeTomessageChannnel();
    }

    subscribeToMessageChannel() {
        if (!this.subscription) {
            this.subscription = subscribe(
                this.messageContext,
                testMC,
                (message) => this.handleMessage(message),
                {
                    scope: APPLICATION_SCOPE
                }
            );
        }
    }
    unsubscribeTomessageChannnel() {
        unsubscribe(this.subscription);
        this.subscription = null;
    }
    handleMessage(message) {
        this.catchEvent = true;
        this._value = message.value;
    }
}

コメント

タイトルとURLをコピーしました