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
angularbeing 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
$broadcastand$onfunctions, targeting a specific iframe from the parent controller uses exactly the same techniques you might use to target a custom directive.
