0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Visualforce に埋め込まれた LWC との通信

Last updated at Posted at 2025-01-25

概要

Visualforce ページに埋め込まれた Lightning Web コンポーネント (LWC) との通信には、以下の方法があります。

  • JavaScript イベントを使用
  • Lightning Message Service (LMS) を使用

これらの実装方法をサンプルコード付きで説明します。

前提条件

JavaScript イベントを使用する方法

サンプルコードの画面構成

image.png

Visualforce ページ

LWC の親となる Visualforce ページです。

  • LWC からのイベントを受信するために、addEventListener 関数を使用してイベントリスナーを追加します。
  • LWC にデータを渡す際は LWC の addVfMessage 関数を呼び出して渡します。
JsEventParent.page
<apex:page>
    <!-- Lightning 関連のライブラリをインポート -->
    <apex:includeLightning />

    <apex:form>
        <apex:pageBlock title="Visualforce">
            <!-- LWC にメッセージを送信するボタン -->
            <apex:pageBlockButtons>
                <apex:commandButton
                    value="LWC にメッセージを送信"
                    onclick="handleSendMessageToLwc();"
                    oncomplete="return null;"
                ></apex:commandButton>
            </apex:pageBlockButtons>

            <apex:pageBlockSection columns="2">
                <!-- LWC からのメッセージ表示領域 -->
                <apex:pageBlockSectionItem>
                    <h2>LWC からのメッセージ</h2>
                    <div class="lwc-message-list"></div>
                </apex:pageBlockSectionItem>

                <!-- LWC 埋め込み領域 -->
                <apex:pageBlockSectionItem>
                    <div id="lwc-container"></div>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>

    <script>
        // Lightning Out を使用して LWC をページに埋め込む
        $Lightning.use('c:jsEventChildContainer', function() {
            $Lightning.createComponent(
                'c:jsEventChild',
                {
                    vfMessages: [{ key: 0, value: 'Hello!', timestamp: new Date().toLocaleTimeString() }]
                },
                'lwc-container',
                function(cmp) {
                    console.log('Visualforce ページに LWC が追加されました:' + cmp);

                    // LWC にイベントリスナーを設定
                    const lwc = document.querySelector('c-js-event-child');
                    lwc.addEventListener('message', handleLwcMessage);
                }
            );
        });

        /**
         * LWC からのメッセージ受信時ハンドラ
         * @param {Event} event イベント
         */
        function handleLwcMessage(event) {
            const lwcMessage = event.detail.message;

            const lwcMessageElement = document.createElement('p');
            lwcMessageElement.textContent = lwcMessage;

            const lwcMessageListElement = document.querySelector('.lwc-message-list');
            lwcMessageListElement.appendChild(lwcMessageElement);
        }

        /**
         * LWC にメッセージを送信する
         */
        function handleSendMessageToLwc() {
            // LWC の @api 関数を呼び出す
            const lwc = document.querySelector('c-js-event-child');
            lwc.addVfMessage('Hello from Visualforce!');
        }
    </script>
</apex:page>

Lightning Web コンポーネント

Visualforce ページに埋め込む LWC です。

  • addVfMessage 関数を Visualforce ページから呼び出せるようにするために @api デコレータを付けます。
  • Visualforce にデータを送信するには、CustomEvent をディスパッチします。
jsEventChild.js
import { LightningElement, api } from 'lwc';

export default class JsEventChild extends LightningElement {
    /**
     * Visualforce からのメッセージ
     * @type {{ key: number; value: string; timestamp: string; }[]}
     */
    @api
    vfMessages = [];

    /**
     * Visualforce からのメッセージを追加する
     * @param {string} message Visualforce メッセージ
     */
    @api
    addVfMessage(message) {
        const newVfMessage = {
            key: this.vfMessages.length,
            value: message,
            timestamp: new Date().toLocaleTimeString()
        };
        this.vfMessages = [...this.vfMessages, newVfMessage];
    }

    /**
     * 「Visualforce にメッセージを送信」ボタン押下時ハンドラ
     */
    handleSendMessageToVf() {
        // CustomEvent を発行
        const event = new CustomEvent("message", {
            detail: {
                message: 'Hello from LWC!'
            }
        });
        this.dispatchEvent(event);
    }
}

Lightning Message Service を使用する方法

サンプルコードの画面構成

image.png

Lightning Message Channel

Visualforce ページと LWC 間で通信するためのメッセージを定義します。

  • message 項目にメッセージ内容を含めます。
  • Visualforce ページと LWC のそれぞれで公開と購読の両方が行われるため、自分自身が公開したメッセージも受信することになります。自分自身が公開したメッセージは読み飛ばす処理を実装するために、「どこから公開されたのか」を表す publisher 項目を用意しています。
Message.messageChannel-meta.xml
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>Message</masterLabel>
    <isExposed>true</isExposed>
    <description>Visualforce に埋め込まれた LWC との通信に使用するメッセージチャネル</description>
    <lightningMessageFields>
        <fieldName>publisher</fieldName>
        <description>公開者。VF:Visualforce, LWC:Lightning Web コンポーネント</description>
    </lightningMessageFields>
    <lightningMessageFields>
        <fieldName>message</fieldName>
        <description>メッセージ</description>
    </lightningMessageFields>
</LightningMessageChannel>

Visualforce ページ

LWC の親となる Visualforce ページです。

  • $Lightning.createComponent 関数の第2引数で、LWC にメッセージチャネル、sforce.one.publishsforce.one.subscribe を渡します。LWC 側ではこれらを使用して LMS を公開・購読します。
LmsParent.page
<apex:page>
    <!-- Lightning 関連のライブラリをインポート -->
    <apex:includeLightning />

    <apex:form>
        <apex:pageBlock title="Visualforce">
            <!-- LWC にメッセージを送信するボタン -->
            <apex:pageBlockButtons>
                <apex:commandButton
                    value="LWC にメッセージを送信"
                    onclick="handleSendMessageToLwc();"
                    oncomplete="return null;"
                ></apex:commandButton>
            </apex:pageBlockButtons>

            <apex:pageBlockSection columns="2">
                <!-- LWC からのメッセージ表示領域 -->
                <apex:pageBlockSectionItem>
                    <h2>LWC からのメッセージ</h2>
                    <div class="lwc-message-list"></div>
                </apex:pageBlockSectionItem>

                <!-- LWC 埋め込み領域 -->
                <apex:pageBlockSectionItem>
                    <div id="lwc-container"></div>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>

    <script>
        // メッセージチャネルを購読する
        const MESSAGE_CHANNEL = "{!$MessageChannel.Message__c}";
        let subscription = sforce.one.subscribe(MESSAGE_CHANNEL, handleInboundMessage, { scope: 'APPLICATION' });

        // Lightning Out を使用して LWC をページに埋め込む
        $Lightning.use('c:lmsChildContainer', function() {
            $Lightning.createComponent(
                'c:lmsChild',
                {
                    messageChannel: MESSAGE_CHANNEL,
                    publish: sforce.one.publish,
                    subscribe: sforce.one.subscribe
                },
                'lwc-container',
                function(cmp) {
                    console.log('Visualforce ページに LWC が追加されました:' + cmp);
                    publishMessage('Hello!');
                }
            );
        });

        /**
         * メッセージチャネル受信時ハンドラ
         * @param {MessageChannel} message メッセージチャネルレコード
         */
        function handleInboundMessage(message) {
            if (message.publisher === 'LWC') {
                const lwcMessage = message.message;

                const lwcMessageElement = document.createElement('p');
                lwcMessageElement.textContent = lwcMessage;

                const lwcMessageListElement = document.querySelector('.lwc-message-list');
                lwcMessageListElement.appendChild(lwcMessageElement);
            }
        }

        /**
         * LWC にメッセージを送信する
         */
        function handleSendMessageToLwc() {
            publishMessage('Hello from Visualforce!');
        }

        /**
         * メッセージチャネルを公開する
         */
        function publishMessage(message) {
            const payload = {
                publisher: 'VF',
                message: message
            };
            sforce.one.publish(MESSAGE_CHANNEL, payload);
        }
    </script>
</apex:page>

Lightning Web コンポーネント

Visualforce ページに埋め込む LWC です。

  • Visualforce から受け取った messageChannelpublishsubscribe を使用して LWS を公開・購読します。

LWC で LMS を使用する一般的は方法は lightning/messageService モジュールをインポートして使用することですが、この方法では Visualforce ページと LWC 間で通信できなかったため、Visualforce ページからメッセージチャネル、sforce.one.publishsforce.one.subscribe を受け取り使用しています。
しかし、この方法は Salesforce のドキュメントに載っていないため、サポートされていない可能性があります。

lmsChild.js
import { LightningElement, api } from 'lwc';

export default class LmsChild extends LightningElement {
    /**
     * メッセージチャネル
     */
    @api
    messageChannel;

    /**
     * メッセージチャネルを公開する
     * @type {(messageChannel: any, payload: any) => void}
     */
    @api
    publish;

    /**
     * メッセージチャネルを購読する
     * @type {(messageChannel: any, listener: (message: any) => void) => any}
     */
    @api
    subscribe;

    /**
     * Visualforce からのメッセージ
     * @type {{ key: number; value: string; timestamp: string; }[]}
     */
    vfMessages = [];

    /**
     * 初期処理
     */
    connectedCallback() {
        // メッセージチャネルを購読する
        if (this.messageChannel && this.subscribe) {
            this.subscribe(this.messageChannel, this.handleInboundMessage.bind(this));
        }
    }

    /**
     * 「Visualforce にメッセージを送信」ボタン押下時ハンドラ
     */
    handleSendMessageToVf() {
        // メッセージチャネルを公開する
        const payload = {
            publisher: 'LWC',
            message: 'Hello from LWC!'
        };
        this.publish(this.messageChannel, payload);
    }

    /**
     * メッセージチャネル受信時ハンドラ
     * @param {MessageChannel} message メッセージチャネルレコード
     */
    handleInboundMessage(message) {
        // 受信したメッセージを「Visualforce からのメッセージ」に表示する
        if (message.publisher === 'VF') {
            const newVfMessage = {
                key: this.vfMessages.length,
                value: message.message,
                timestamp: new Date().toLocaleTimeString()
            };
            this.vfMessages = [...this.vfMessages, newVfMessage];
        }
    }
}

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?