AngularJS: open a new browser window, yet still retain scope and controller, and services
W

3

29

I'm writing an angularJS app. In this particular controller, I open a new browser window through the $window.open service. But in the new window, all the $scope variables are lost.

I tried to use window.parent but this doesn't work. In fact in the new browser window all the app services, controllers, or scopes are not in effect at all, is this true? Is there a way to open a new browser window yet still makes the new window belongs to the same angular app in the old window? I need to have access to some angularJS services and the scope of the controller that open that new window. Is this possible at all?

Weatherly answered 3/2, 2014 at 3:8 Comment(3)
Do you need to open a new window? Or would something like a modal window work, where you can inject the scope. angular-ui.github.io/bootstrap/#/modal. Running a new window instance with the same scope may get very messy.Stoned
If you open a new window, you have full html. So, you need another ng-app declaration.Automobile
hi there, no, I can't use modal window, I'm trying to display a table with lots of rows, modal window will make the UI look super ugly.Weatherly
Z
29

There is no [straightforward] way to make the new window belong to the same angular.js application, since the angular application is generally tied to the document, window, and events of the window where it was initialized either via an ng-app directive or by calling angular.bootstrap.

However, you can create a new angular module and application for your popup window. You could use the same basic services and controllers from your original application by including the appropriate javascript files.

Presuming your popup window needs data from the original application, you can pass that by using the window object returned from the window.open() method. For example, within your first angular application, open your popup window like so:

angular.module('originalModule').service('popupService', function(someOtherDataService) {

  var popupWindow = window.open('popupWindow.html');
  popupWindow.mySharedData = someOtherDataService.importantData;

});

Once your secondary "popup" angular application is initialized, it can then reference the shared data by reading window.mySharedData.

You can also create functions in each window that can be called from the other window. The popup window can call back into the original window by using the window.opener property. (window.parent refers to the parent window of frames, you want window.opener)

[Agreed, I'm sure that if you studied the angular source code you could find some clever way to use the same angular app for both windows. Such an attempt is beyond my ambition this evening.]

Zone answered 3/2, 2014 at 3:35 Comment(4)
Where there is will, there are hacks :)Veloz
hi, I ended up not making a new angular app. I did use your techniques of setting the shared data through window.mySharedData, in fact I think you can export the $scope and all the $service you need through such techniques. Thanks.Weatherly
@Weatherly It'll be really helpful if you can share your final code.Ethelstan
This article demonstrates a way to achieve what the OP wantsIrreclaimable
S
9

A window which is opened by your main window will architecturally be unable to share the same root scope with its parent. Because the angular scope is defined per DOM element. You need to bootstrap a completely new AngularJs app in the child window.

Provided a new window (child), which hosts another AngularJs application, has been spawned by the main window (parent), a following solution may be viable: referencing the root scope of the newly spawned window from the parent window and then communicating an event through the scope of the child window from the parent. Something like this:

On the child window:

$rootScope.$on("INTER_WINDOW_DATA_TRANSFER", function (data, args) {                   
            console.log("DATA RECEIVED: " + args.someData);
        });

From the parent window you take hold of the DOM element (in the child window) on which the ng-app attribute is defined (it's root scope) (pseudocode):

var newWindowRef = $window.open("", "New Window", "width=1280,height=890,resizable=1");
var newWindowRootScope = newWindowRef.angular.element("#MY_ROOT_APP_ELEMENT_ID").scope();
newWindowRootScope.$broadcast("INTER_WINDOW_DATA_TRANSFER", {someData : "I'm data"});
Syce answered 27/2, 2014 at 15:45 Comment(1)
This is not a very good solution. $window.open doesn't wait for the document to be ready before returning the new window handle. Referencing the element of the child window will return Undefined unless that window opened really fast. Additionally the user may have a popup blocker. The safest way is for the child to call the parent(window.opener) to get what it needs.Autoerotism
G
6

You can pass data by using window object :

Syntax:

$window.open('<linkname>').<variableName> = "your data";

Example :

$window.open('<linkname>').var1 = "value1";

(Note:- This one will open new link and set variable data) In new page controller you can access variable by using oldata = window.var1;

Globoid answered 8/7, 2016 at 7:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.