Reputation: 2749
I have a page A, which contains two iFrames B and C. Both B and C are trusted and under my control. B and C each use AngularJS. I'd like to use the scope of an inner element on page B as the scope for an element on page C.
More concretely,
Page A:
...
<iframe src="Page B"/>
<iframe src="Page C"/>
...
Page B:
...
<div id="trunk-element" ng-controller="PageBController">
{{pageBModel.text}}
</div>
...
Page C:
...
<div id="grafted-element">
{{pageBModel.text}}
</div>
...
How do i get #grafted-element to "take on the scope" of #trunk-element? That is, I'd like #grafted-element to act exactly as if it was included inside #trunk-element on page B. I have a reference to #trunk-element's scope in page C.
Some stuff I've tried:
Overwriting the '$scope' data attribute of #grafted-element. This gets reverted.
Creating a controller on page C for which I replace the $parent and __proto__ properties of $scope to #trunk-element's scope. Then I enclose #grafted-element in that controller. This works, but the rendering does not update when pageBModel.text changes.
Upvotes: 1
Views: 705
Reputation: 2749
I ended up solving this by hijacking the scope of the controller more fully. Specifically:
Javascript for page C:
// copypasta from angular's $new
var adoptScope = function(parent, child) {
child.$$listeners = {};
child.$parent = parent;
child.__proto__ = parent;
child.$$watchers = null;
child.$$nextSibling = null;
child.$$childHead = null;
child.$$childTail = null;
child.$$prevSibling = parent.$$childTail;
if (parent.$$childHead) {
parent.$$childTail.$$nextSibling = child;
parent.$$childTail = child;
} else {
parent.$$childHead = parent.$$childTail = child;
}
child.$root = parent.$root;
child.$$asyncQueue = parent.$$asyncQueue;
child.$$postDigestQueue = parent.$$postDigestQueue;
};
myApp.controller('ExternalCtrl', function($scope) {
adoptScope(wScope, $scope);
});
And the html for page C:
...
<div ng-controller="ExternalCtrl">
{{pageBModel.text}}
</div>
...
Where wScope is the angular scope of #trunk-element.
Upvotes: 1