angularjs $ compile会在iframe上发生onload事件

时间:2015-08-24 19:39:17

标签: javascript html angularjs iframe

我正在尝试创建一个接收模板和范围的打印提供程序,并将其编译为html,而不是在body标签中插入带有此html内容的iframe,并在iframe上的onload事件上调用print打印此内容。 代码如下所示:

myApp.provider('$print', function() {
    return {
        $get: function($document, $interpolate, $compile, $timeout) {
            var $print = {};

            function printFrame(content) {
              var frameContent = '<!doctype html>' +
                  '<html>' +
                    '<body onload="window.print()">' +
                      content +
                    '</body>' +
                  '</html>';

              // inject iframe into DOM
              var iframe = document.createElement("IFRAME");
              iframe.id = 'print-frame';
              iframe.style.display = 'none';

              var body = $document.find('body').eq(0);
              body.append(iframe);
              iframe = document.getElementById('print-frame');

              // fill iframe with print content
              var iframeContent = (iframe.contentWindow) ? iframe.contentWindow : (iframe.contentDocument.document) ? iframe.contentDocument.document : iframe.contentDocument;
              iframeContent.document.open();
              iframeContent.document.write(frameContent);
              iframeContent.document.close();
            };

            $print.iframe1 = function(printOptions) {
                var printScope = printOptions.scope.$new();
                var htmlToPrint = $interpolate(printOptions.template)(printScope);
                printFrame(htmlToPrint);
            }

            $print.iframe2 = function(printOptions) {
                var printScope = printOptions.scope.$new();
                $timeout(function() {
                    var htmlToPrint = $compile(printOptions.template)(printScope);
                    printScope.$digest();
                    printFrame(htmlToPrint.html());
                });
            }

            return $print;
        }
    }
});

我遇到的问题是,当我使用$interpolate时,提供程序工作正常,iframe onload事件等待,直到图像和所有内容在调用打印之前加载,但是我使用$compile,出于某种原因,iframe的onload事件会在加载图片之前触发。

我为这个例子创建了一个JSFiddle,如果你禁用缓存,你可以看到插值的方式,只在加载了大图像后才调用print,但是在编译时,打印信息会立即打开。

希望有人可以帮助我,提前谢谢,丹尼尔!

http://jsfiddle.net/HB7LU/16737/

1 个答案:

答案 0 :(得分:2)

htmlToPrint确实有两个元素h1&amp;另一个是img标记,但问题是当您从htmlToPrint.html()函数执行iframe2时它只会返回SuperHero,它不会返回html的其他部分。

为了解决这个问题,你可以使用你需要用一些div包装模板,这样在元素上执行.html()时将返回正确的元素。

<强>模板

template: '<div>'+
            '<h1>{{printTitle}}</h1>'+
            '<img style="width: 1000px" src="http://velocityagency.com/wp-content/uploads/2013/08/go.jpg"'>+'
          '<div>',

此外,您需要在10函数中设置一些少量的超时,例如$timeout

$timeout(function() {
    printFrame(htmlToPrint.html());
},10);

Working Fiddle

<强>更新

如果我禁用了浏览器缓存,上面的解决方案并不起作用,我想我们在页面上渲染图像之前会发送一个页面进行打印。

$print.iframe2 = function(printOptions, scope) {
    var printScope = printOptions.scope.$new();
    var htmlToPrint = $compile(printOptions.template)(printScope);

    angular.element(htmlToPrint.find('img').on('load', function() {
        $timeout(function() {

            console.log("Img loaded")
            printFrame(htmlToPrint.html());
        });
    }))

}

Updated Fiddle