嵌入在iframe resize事件中的Angular2应用程序

时间:2017-03-13 11:16:48

标签: javascript angularjs angular typescript iframe

我在Liferay portlet中有一个Angular2应用程序。 Liferay tomcat与angular2应用程序在不同的域中。我正在尝试根据iframed应用程序的高度调整iframe的大小。我在Liferay的tomcat上使用帮助文件来做到这一点 - 基于答案Resizing an iframe based on content

这是我到目前为止所得到的: 带有父应用程序的tomcat上的helper.html:

<html>
<!-- 
This page is on the same domain as the parent, so can
communicate with it to order the iframe window resizing
to fit the content 
-->
<body onload="parentIframeResize()">
<script>
    // Tell the parent iframe what height the iframe needs to be
    function parentIframeResize()
    {
        var height = getParam('height');
        // This works as our parent's parent is on our domain..
        parent.parent.resizeIframe(height);
    }

    // Helper function, parse param from request string
    function getParam( name )
    {
        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( window.location.href );
        if( results == null )
            return "";
        else
            return results[1];
    }
</script>
</body>
</html>

使用iframe的portlet中的Jsp文件:

<iframe id="iframed-application"
        src="${baseUrl}:${externalTomcatPort}/${applicationName}/iframe?baseUrl=${baseUrl}:${port}">
</iframe>

<script>
    // Resize iframe to full height
    function resizeIframe(height) {
        document.getElementById('iframed-application').height = parseInt(height) + 10;
    }
</script>

Angular2 app.component.html

<menu></menu>
<router-outlet></router-outlet>
<iframe id="helpframe" [src]='helperSource' height='0' width='0' frameborder='0'></iframe>

Angular2 app.component.ts

import {Component} from "@angular/core";
import {OnInit} from "@angular/core";
import {ContextService} from "./common/service/context.service";
import {DomSanitizer} from "@angular/platform-browser";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    helperSource;

    constructor(private sanitizer: DomSanitizer, private context: ContextService) {
    }

    ngOnInit(): void {
        let height = window.innerHeight;
        if (height < 800) height = 800;
        this.helperSource = this.sanitizer.bypassSecurityTrustResourceUrl(this.context.baseUrl + '/helper/helper.html' + '?height=' + height);
    }
}

当调用ngOnInit时,模板尚未渲染,因此它总是将iframe高度设置为800px,但主要问题是不同的。如何在iframe中检测角度应用内容的resize事件?我试过用:

@HostListener('window:resize', ['$event'])

但它正在侦听整个窗口的大小调整,而不是iframe。

我的第二次尝试就像是:

let iframe: HTMLIFrameElement = <HTMLIFrameElement> document.getElementById('iframed-application');
    let contentWindow: Window = iframe.contentWindow;
    contentWindow.onresize = event => {

};

但它也失败了,因为document.getElementById返回null - 正如我从安全原因所理解的那样 - 跨域。

无论如何可以听取iframed应用程序的大小调整,或者还有其他方法吗?

2 个答案:

答案 0 :(得分:1)

我们找到的唯一解决方案是将此绑定到正文上的onclick事件,例如:

str = "(((MILK AND SOYA) OR NUT) AND COCONUT)"
while not str.nil?
    puts str = str.match(/\((.*)\)/).to_a.last
end # => 
((MILK AND SOYA) OR NUT) AND COCONUT
(MILK AND SOYA) OR NUT
MILK AND SOYA

答案 1 :(得分:1)

这是一个执行它的指令

    import {Directive, ElementRef, OnInit, Renderer} from "@angular/core";

@Directive({
    selector: "[iframeAutoHeight]"
})
export class IframeAutoHeightDirective implements OnInit {
    private el: any;
    private renderer: Renderer;
    private prevHeight: number;
    private sameCount: number;

    constructor(_elementRef: ElementRef, _renderer: Renderer) {
        this.el = _elementRef.nativeElement;
        this.renderer = _renderer;
    }

    ngOnInit() {
        const self = this;
        if (this.el.tagName === "IFRAME") {
            this.renderer.listen(this.el, "load", () => {
                self.prevHeight = 0;
                self.sameCount = 0;
                setTimeout(() => {
                    self.setHeight();
                }, 50);
            });
        }
    }

    setHeight() {
        const self = this;
        if (this.el.contentWindow.document.body.scrollHeight !== this.prevHeight) {
            this.sameCount = 0;
            this.prevHeight = this.el.contentWindow.document.body.scrollHeight;
            this.renderer.setElementStyle(
                self.el,
                "height",
                this.el.contentWindow.document.body.scrollHeight + "px"
            );
            setTimeout(() => {
                self.setHeight();
            }, 50);

        } else {
            this.sameCount++;
            if (this.sameCount < 2) {
                setTimeout(() => {
                    self.setHeight();
                }, 50);
            }
        }
    }
}

用法:

<iframe [src]="iframeUrl" iframeAutoHeight></iframe>