1

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.

4
  • From the controller in Page C, have you tried something like $scope.pageBText = angular.element(parent.iFrameBName.getElementById("trunk-element")).scope().text? Then maybe you would have to set up a $watch, not sure. Commented Nov 6, 2013 at 0:07
  • Sorry but I stopped reading after iFrames. Is there no other way to solve the problem without the use of iframes? Commented Nov 6, 2013 at 0:09
  • It is possible to set up a watch, but this would result in a lot of duplication. The reason there are iframes is because this is actually within a firefox extension. Page A can't run angular (it is a xul page). Pages B and C are two pieces of the same app, but separated ui-wise. Commented Nov 6, 2013 at 0:16
  • Do I get it right? You try to share data using scope? If so, use a Service instead which you inject into the controller and inside the controller you assign the value to the scope. Commented Nov 6, 2013 at 0:42

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.