Monday

postMessage API >> send messages & call parent's js function: between jsp and react app (in iframe)

I tried to:
- open a react app in an iframe from jsp
- send message by postMessage API>> from jsp to react, from react to jsp
- call parent's function by postMessage API inside iframe(react app)

http://localhost:8080 >> jsp 
http://localhost:3000 >> react

jsp example:
 ....
<tiles:put name="body" type="string">
   
 <div id="reactIframeLoading" style="height:50px; color:red; font-size:12px; 
      margin-left:2px;">
      React Iframe Loading...<br> 
      <a href="javascript:loadReactIframe()">Retry</a>
 </div> 

 <iframe 
      id="reactIframe" 
      style="display:none;"
      onload="reactIframePostMessage(); reactIframeLoaded();"
      src="http://localhost:3000/"
      width="100%" height="200" border="0" marginwidth="0"
      marginheight="0" scrolling="no">
 </iframe> 
  
 <script type="text/javascript">    
     const dataForReactPostMessage = {
           isReadOnly: false,
           someData: {
               someDataChild: 'eda'
          }
      }

     function callMeFromReact(msg) {
         console.log('callMeFromReact: params: ' + msg);
     }
  
     function reactIframeLoaded() {
        document.getElementById("reactIframe").style.display='';
        document.getElementById("reactIframeLoading").style.display='none';
     }  
  
     function loadReactIframe(){
         document.getElementById("reactIframe").src="http://localhost:3000/";
     }
  
     function reactIframePostMessage(){
         document.getElementById("reactIframe").contentWindow.postMessage(
              dataForReactPostMessage, 'http://localhost:3000/'
         );
     }
  
    window.addEventListener('message', handleFrameTasks);

    //get messages from iframe or run function given by iframe  
     function handleFrameTasks(event) {
           if(event.origin !== "http://localhost:3000") {
              return;
           }

           //if function is given
           var data = event.data;
           if(typeof(window[data.func]) == "function") {
                 window[data.func].call(null, data.params[0]);

          //if data is given
          } else if(data.event_id === 'my_first_message') {
                console.log('post message from react to jsp // event_id: my_first_message= ' + JSON.stringify(event.data));
          }
     }
  </script>
</tiles:put>

react example:
import React, { Component } from 'react'

class Example extends Component {

    constructor(props) {
        super(props);
        this.handleFrameTasks = this.handleFrameTasks.bind(this);
        this.sendParentPostMessage = this.sendParentPostMessage.bind();
    }

    componentWillMount() {
        window.addEventListener('message', this.handleFrameTasks);
    }

    componentWillUnmount() {
        window.removeEventListener("message", this.handleFrameTasks);
    }

    handleFrameTasks(event) {
        if(event.origin !== "http://localhost:8080") {
           return;
        }
        console.log('postmessage from jsp to react // event.data= ' + JSON.stringify(event.data));
    }

    sendParentPostMessage() {
        const dataForJspPostMessage = {
            event_id: 'my_first_message',
            someData: {
                someDataChild1: 'eda 1', 
                someDataChild2: 'eda 2'
            }
        } 
        //send data to parent
        window.parent.postMessage(dataForJspPostMessage, 'http://localhost:8080'); 

        //call js function named as 'callMeFromReact' in parent
        window.parent.postMessage(
            {'func':'callMeFromReact','params':['SomeMessages']}, 
            'http://localhost:8080'
        ); 

        window.parent.postMessage(
            {'func':'nonExistingMethod','params':['SomeMessages']}, 
            'http://localhost:8080'
        );
    }

    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <button onClick={this.sendParentPostMessage}>sendParentPostMessage</button>
            </div>
        );
    }

}

export default Example

UPDATE: last version for post message listener:
window.addEventListener('message',  function (event) {
      if(event.origin != null && event.origin.includes(".int.teb.com.tr")) {
            var data = event.data;
            if(data != null && typeof(window[data.func]) == "function"){
                if(data.params != null && data.params.length > 1) {
                  var args = new Array();
                  for(var i = 0; i < data.params.length; i++){
                       args.push(data.params[i]);
                  }

                  window[data.func].apply(this, args);
                  
                } else {
                  window[data.func].call(null, data.params);
                }
            }
      }
}); 

1 comment: