Sergiu Toarca
Sergiu Toarca

Reputation: 2749

Bind element to existing AngularJS scope in a different frame

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

Answers (1)

Sergiu Toarca
Sergiu Toarca

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

Related Questions