Angular中iFrame的onLoad函数

57

我用基本的JavaScript让这个iframe工作:

<iframe id="upload_iframe" name="upload_iframe" onLoad="uploadDone();"></iframe>

当 iframe 的内容加载完毕时,触发 uploadDone(); 方法。

在 Angular 中如何实现相同的效果?我想在 iframe 加载时调用控制器上的函数,但是到目前为止我还没有看到 ng-onload

5个回答

121

评论一年前的问题。 对于存在多个iframe的情况,我需要绑定“onload”事件。 我采用了这种方法。

指令

APP.directive('iframeOnload', [function(){
return {
    scope: {
        callBack: '&iframeOnload'
    },
    link: function(scope, element, attrs){
        element.on('load', function(){
            return scope.callBack();
        })
    }
}}])

控制器

APP.controller('MyController', ['$scope', function($scope){

    $scope.iframeLoadedCallBack = function(){
        // do stuff
    }
}]);

文档对象模型(DOM)

<div ng-controller="MyController">
    <iframe iframe-onload="iframeLoadedCallBack()" src="..."></iframe>
</div>

2
太好了,感谢这个指令。我在指令中改变了回调函数的调用方式:return scope.callBack(element); 这样我就可以在我的函数中读取元素属性了。 - Pandaiolo
嗯,你甚至可以将其返回为一个 Promise! - Miguel Felipe Guillen Calo
2
我尝试传递元素,但无法访问,你能分享一个小的可工作演示吗? - tomalex
1
确保你的回调是一个函数, iframe-onload="iframeLoadedCallBack()"确保你的回调接受一个参数 $scope.iframeLoadedCallBack = function(element) {...} - Miguel Felipe Guillen Calo
19
Miguel,你的解决方案非常好!但请为那些复制粘贴代码的人解除销毁时的事件处理程序的绑定:scope.$on('$destroy', function() { element.off('load'); })。请注意不要更改原文意思,尽可能使翻译通俗易懂。 - ra00l
显示剩余2条评论

34

如果你使用的是 Angular 2+,那么很简单:

<iframe (load)="uploadDone()"></iframe>

没有全局函数,适用于多个iframe。


@hajjin 我怎样才能在上传完成之前显示加载器? - Arul
你可以定义一个变量showLoader,并根据它的值来显示加载器。在开始加载后将其设置为true,在uploadDone中将其设置为false。 - Haijin
在 Angular 上下文中,这绝对是正确的答案。 - millenion

29
尝试将函数定义在控制器内部,如下所示:
window.uploadDone=function(){
  /* have access to $scope here*/
}

1
有没有选项可以传递Angular参数?例如: code<div ng-repeat="item in items"> <iframe src="{{item.url}}" onload="iframeLoaded(item)" /> - Leon
4
这样做的缺点是它把全局函数和Angular代码混在了一起。虽然可以运行,但可能会造成混淆。例如,“其他人阅读代码时是否期望在控制器中找到它?它会与其他任何东西冲突吗?” - Adam Zerner

4

如果有人到了这里,ng-onload 插件是解决这个问题的完美方案。它不会污染全局命名空间,并且在您只想调用一个简单的作用域函数时,不需要创建一次性指令。


在Angular 1.5.x中,ngOnload似乎在contentWindow方面返回undefined。您是否在此版本的AngularJS上使用过它并使其正常工作? - mtpultz

1
对于那些动态注入iframe的人,你可以按照以下步骤进行操作。
HTML...
<div #iframeContainer></div>

ts...

@Component({
  selector: 'app-iframe-onload',
  templateUrl: './iframe-onload.component.html'
})
export class IframeOnload implements AfterViewInit {

@ViewChild('iframeContainer') iframeContainer: ElementRef;

ngAfterViewInit(): void {
  this.injectIframe();
}

private injectIframe(): void {
  const container = this.iframeContainer.nativeElement;
  const iframe = document.createElement('iframe');
  iframe.setAttribute('width', '100%');
  iframe.setAttribute('src', 'https://example.com/');
  iframe.setAttribute('height', 'auto');
  iframe.setAttribute('frameBorder', '0');
  iframe.addEventListener('load', this.iframeOnLoadtwo);
  container.appendChild(iframe);

}

public iframeOnLoadtwo(): void {
  console.log('iframe loaded...');
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接