AngularJS postmessage iframe

时间:2014-07-01 17:01:06

标签: angularjs iframe postmessage

我正在寻找一种获取iframe contentWindow对象的方法,并在用户执行某些操作后向其发布消息。我目前的解决方案根本没有角度感觉好(特别是从控制器访问DOM)。

我创建了一个说明问题的plunker: http://plnkr.co/edit/aXh4jydWGWfK3QQD4edd

执行postMessage是一种更有棱角的方式吗?

控制器:

app.controller('Main', function($scope) {
  $scope.click = function() {
    var iframe = document.getElementById("inner").contentWindow;

    iframe.postMessage("Hello iframe", '*');
  }
});

HTML:

  <body ng-controller="Main">
    <button ng-click="click()">send message</button>

    <iframe id="inner" src="inner.html"/>
  </body>

1 个答案:

答案 0 :(得分:3)

我知道你的问题已经超过一年了,但我最近有类似的需求,所以我想我会发布我的解决方案。最初我有像你发布的东西,但正如你所指出的那样,这并不是非常“有角度”。它也不容易测试,我认为它也不是非常“Angular”。

相反,我重构了我的代码以实现iframe作为指令。然后我从应用程序的控制器发出$broadcast()个事件并让指令听取它们。这段代码可能会有相当多的改进,但感觉更像“Angular”并且避免直接触摸DOM。

'use strict';

angular.module('app')
    .directive('angularIframe', ['$rootScope', function($rootScope) {

        return {
            restrict: 'E',
            replace: true,
            template: '<iframe id="game" src="/iframe/index.html" width="100%" height="100%" frameboarder="0" scrolling="no"></iframe>',
            link: function(scope, elem) {

                var off = $rootScope.$on('app.postmessage', function(ev, data, targetOrigin) {

                    var str = JSON.stringify(data);
                    targetOrigin = targetOrigin || '*';
                    elem[0].contentWindow.postMessage(str, targetOrigin);

                });

                // See: http://stackoverflow.com/a/14898795/608884
                elem.on('$destroy', function() {
                    off();
                });

            }
        };
    }]);

然后,您可以通过在应用程序中的某处添加<game></game>来使用此指令。

在控制器中,您现在可以广播app.postmessage事件以及一些数据,以便在postMessage()上调用iframe

var myData = { foo: 'bar' };
$rootScope.$broadcast('app.postmessage', myData);