Angular 2 iframe to parent communication
I am looking at doing something similar at the moment (a portal application with sub apps in an iFrame) You can communicate between your server and client (in either direction) by using window.postMessage to send data.
So for example on the server app:
var iframe = document.getElementById('useriframe');
if (iframe == null) return;
var iWindow = (<HTMLIFrameElement>iframe).contentWindow;
iWindow.postMessage({"for":"user","data":"anything"}, 'http://localhost:4001');
and on the client app (hosted within the iFrame)
export class AppComponent {
@HostListener('window:message',['$event'])
onMessage(e)
{
if (e.origin!="http://localhost:4200")
{
return false;
}
if (e.data.for=="user")
{
alert('here i am');
}
}
Showing child frame routes in the parent So, in my implementation we pass tokens and user information from the shell application to the child iFrame, and we pass routing information from the child applications back to the shell so that the url reflects the route selected in the child application. In a child application you may have a route such as:
[userapp]/edituser/username
, and we wish to post it to the parent application and display the route like:
http://mywebsite/main/application/user#edituser/bob
Note that we use hashtag to mark a child route, and in your child applications you intercept every navigation event and post the new route via
export class MyRoutingComponent implements OnInit {
constructor(private router: Router) {
router.events.subscribe((event: Event)=>{
if (event instanceof NavigationEnd){
let url=(<NavigationEnd>event).url;
if (url.length>1)//don't post message about base route '/'
window.parent.postMessage({"for":"dashboard", "operation":"changeroute","route":url},'*')
}
})
}
and then in the parent application parse the message and use it to update the location path displayed.
url = url +'#' + route;
this.location.go(url);
Hi really appreciate the solution given by @jazza1000 it helped me out.
Our problem was in the current (to date) version of angular cli there is a bug that prevents the use of external JS files even with allowJs. We would be using jsplumb (external js) to represent some flow charts. (Actual issue on stack overflow)
So we decided to go with the approach of hosting the functionality that uses external JS in an additional angular 4 application. And the parent angular 5 application will bring in the angular 4 application with iFrame. So when the user would want to view the flowchart we would open angular4 application in iframe then once he is done he would click save in the angular 4 application that would save all his modification followed by sending the message to parent window that would close/hide the div with iframe.
Our parent application in angular 5 has the code
@HostListener('window:message', ['$event'])
onMessage(e) {
debugger;
if (e.origin != "http://localhost:4201") { // set your origin
return false;
}
if (e.data.for == "user") {
alert('here i am');
}
}
Our iFrame angular 4 application on save button has the code (we are starting the application with --port 4201)
window.parent.window.postMessage({"for":"user","data":"anything"}, 'http://localhost:4200')