LoginSignup
6
5

More than 5 years have passed since last update.

Lightning コンポーネントと iframe 内の Visualforce ページで相互通信する

Posted at

今回は Lightning コンポーネントによって iframe で読み込まれた Visualforce ページと、呼び出し元の Lightning コンポーネントでメッセージのやり取りをする方法です。

Web Messaging API を使う

iframe を使って読み込まれた Visualforce ページとの通信には JavaScript の Web Messaging API が使えます。
(Web Messaging API の詳細については省きます)

基本的な方針は、まず Lightning コンポーネントで MessageChannel を作成し window オブジェクトの postMessage() を介して Visualforce ページに片方の MessagePort を渡します。それ以降は、それぞれの MessagePort の postMessage() を利用し通信する事で 1 対 1 のコミュニケーションを確立します。

window.postMessage() の問題点

Lightning コンポーネントと Visualforce ページ間のコミュニケーションは window.postMessage() だけでも実現できます。
しかし、これは window オブジェクトに対してメッセージを送信してしまうので、同じ window オブジェクトを共有している全員がメッセージを受け取れてしまうという点で注意が必要です。
Visualforce ページは、それぞれのフレーム内で異なる window オブジェクトを持ちますが、 Lightning コンポーネントは同じ window オブジェクトを共有しています。
つまり、 Visualforce ページから送信されたメッセージが予期せぬ Lightning コンポーネントによって読み取られる可能性があります。

Screen Shot 2019-03-19 at 17.51.02.png

サンプルコード

上記の基本方針に沿ったサンプルコードです。

MessageExample.cmp
<aura:component access="global" implements="flexipage:availableForAllPageTypes"  >
    <!-- User Interface -->
    <iframe aura:id="iframe" src="/apex/VFPage" onload="{!c.onLoad}" />
</aura:component>
MessageExampleController.js
({
    onLoad: function(c, e, h) {

        // MessageChannel を作成する
        const channel = new MessageChannel();

        // Lighting コンポーネントは port1 を利用する事として、メッセージハンドラーを登録する
        // このハンドラーでは、Visualforce ページから送信されたメッセージをコンソールに出力した後、
        // 同じメッセージを Visualforce ページに送信する
        const port1 = channel.port1;
        port1.onmessage = function(event) { 
            console.log('Lighting Component received: ', event.data);
            port1.postMessage(event.data);
        }

        // port2 は Visualforce ページに渡す
        const contentWindow = c.find('iframe').getElement().contentWindow;
        contentWindow.postMessage('', '*', [channel.port2]);
    },
})
VFPage.vfp
<apex:page>
    <script>
    // Lightning コンポーネントから window.postMessage() によって MessagePort が渡されるのを待つ
    window.addEventListener('message', function(event) {

        // MessagePort を受け取ったら、メッセージハンドラを登録し、
        // Lightning コンポーネントにメッセージを送信する
        // Lightning コンポーネントからメッセージを受け取ったら、コンソールに出力する
        const port2 = event.ports[0];
        port2.onmessage = function (e) {
            console.log('Visualforce Page received : ', e.data);
        };
        port2.postMessage('Hello!');
    }, false);
    </script>
</apex:page>
6
5
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
6
5