Same-domain iframe communication
AngularJS scope events for same-domain bi-directional iframe communication
It's possible for Angular apps to communicate, where one is running in an iframe of a parent, using standard scope events. This means you can treat an iframe much like a custom directive, responding to $broadcast
-ed events, or $emit
-ting its own.
This technique relies on the child app being able to access the $scope
of the iframe element in the parent app. This is possible by using $window.frameElement
to access the iframe element from within the child window, and the angular.element
scope
function to get its $scope
. The child app can then call the parent app's $on
and $emit
functions.
For simplicity, I've opted to create a small factory in the child app that returns the scope of the iframe in the parent app. This way, it can be used in a very similar way to $rootScope
.
appInIframe.factory('$parentScope', function($window) {
return $window.parent.angular.element($window.frameElement).scope();
});
Then in any controller in the child app that wants to communicate with the parent, you can use these functions as per the following example.
appInIframe.controller('ChildController', function($scope, $parentScope) {
$scope.messages = [];
$scope.message = function() {
$parentScope.$emit('from-iframe','Sent from iframe');
$parentScope.$apply();
};
$parentScope.$on('from-parent', function(e, message) {
$scope.messages.push(message);
$scope.$apply();
});
});
The only thing you should remember is that you need to trigger a digest manually in each app.
The controller in the parent app can then use standard $broadcast
and $on
to commnicate to the iframe.
appInParentWindow.controller('ParentController', function($scope) {
$scope.messages = [];
$scope.$on('from-iframe', function(e, message) {
$scope.messages.push(message);
});
$scope.message = function() {
$scope.$broadcast('from-parent', 'Sent from parent');
};
});
You can see an example of this technique in a plunker.
Benefits of this technique over some others are given below.
- No additional global functions added to either the parent or the iframe window. Although yes, it does depend on
angular
being global in the parent window. - The parent controller is ignorant of the fact that events go into an iframe.
- IDs are not used by parent or child. Because the parent uses the standard
$broadcast
and$on
functions, targeting a specific iframe from the parent controller uses exactly the same techniques you might use to target a custom directive.