AngularJS:打开一个新的浏览器窗口,但仍保留范围和控制器以及服务

Posted

技术标签:

【中文标题】AngularJS:打开一个新的浏览器窗口,但仍保留范围和控制器以及服务【英文标题】:AngularJS: open a new browser window, yet still retain scope and controller, and services 【发布时间】:2014-02-26 10:51:24 【问题描述】:

我正在编写一个 angularJS 应用程序。在这个特定的控制器中,我通过$window.open 服务打开了一个新的浏览器窗口。但在新窗口中,所有$scope 变量都丢失了。

我尝试使用window.parent,但这不起作用。事实上,在新的浏览器窗口中,所有应用服务、控制器或范围都没有生效,这是真的吗?有没有办法打开一个新的浏览器窗口但仍然使新窗口属于旧窗口中的同一个角度应用程序?我需要访问一些 angularJS 服务和打开该新窗口的控制器的范围。这可能吗?

【问题讨论】:

您需要打开一个新窗口吗?或者像模态窗口一样工作,您可以在其中注入范围。 angular-ui.github.io/bootstrap/#/modal。运行具有相同范围的新窗口实例可能会变得非常混乱。 如果你打开一个新窗口,你有完整的html。所以,你需要另一个ng-app 声明。 嗨,不,我不能使用模态窗口,我正在尝试显示一个有很多行的表格,模态窗口会使 UI 看起来超级难看。 【参考方案1】:

您可以使用窗口对象传递数据:

语法:

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

例子:

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

(注意:- 这将打开新链接并设置可变数据) 在新页面控制器中,您可以使用访问变量 oldata = window.var1;

【讨论】:

【参考方案2】:

由您的主窗口打开的窗口在架构上将无法与其父窗口共享相同的根范围。因为角度范围是按 DOM 元素定义的。您需要在子窗口中引导一个全新的 AngularJs 应用程序。

如果主窗口(父)已经生成了一个承载另一个AngularJs应用程序的新窗口(子),则以下解决方案可能是可行的:从父窗口引用新生成的窗口的根范围,然后通过父窗口的子窗口范围传递事件。像这样的:

子窗口上:

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

从父窗口,您获取定义了 ng-app 属性的 DOM 元素(在子窗口中)(它是根范围)(伪代码):

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");

【讨论】:

这不是一个很好的解决方案。 $window.open 在返回新窗口句柄之前不会等待文档准备好。引用子窗口的元素将返回 Undefined ,除非该窗口打开得非常快。此外,用户可能有一个弹出窗口阻止程序。最安全的方法是让孩子调用父母(window.opener)来获取它需要的东西。【参考方案3】:

没有 [直接] 方法可以使新窗口属于同一个 angular.js 应用程序,因为 Angular 应用程序通常与文档、窗口和窗口的事件相关联,通过 ng 初始化它-app 指令或通过调用 angular.bootstrap。

但是,您可以为弹出窗口创建一个新的 Angular 模块和应用程序。通过包含适当的 javascript 文件,您可以使用与原始应用程序相同的基本服务和控制器。

假设您的弹出窗口需要来自原始应用程序的数据,您可以使用从 window.open() 方法返回的窗口对象来传递它。例如,在您的第一个 Angular 应用程序中,像这样打开您的弹出窗口:

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

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

);

一旦您的辅助“弹出式”角度应用程序被初始化,它就可以通过读取 window.mySharedData 来引用共享数据。

您还可以在每个窗口中创建可以从另一个窗口调用的函数。弹出窗口可以通过使用 window.opener 属性回调到原始窗口。 (window.parent指的是frame的父窗口,你要window.opener)

[同意,我敢肯定,如果您研究了 Angular 源代码,您会找到一些巧妙的方法来为两个窗口使用相同的 Angular 应用程序。这样的尝试超出了我今晚的野心。]

【讨论】:

有志者事竟成 :) 嗨,我最终没有制作一个新的 Angular 应用程序。我确实使用了您通过 window.mySharedData 设置共享数据的技术,实际上我认为您可以通过这些技术导出 $scope 和您需要的所有 $service。谢谢。 @phamductri 如果你能分享你的最终代码,那将非常有帮助。 This 文章演示了一种实现 OP 想要的方法

以上是关于AngularJS:打开一个新的浏览器窗口,但仍保留范围和控制器以及服务的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS UI 路由器 - 在新的浏览器选项卡中使用数据打开状态

为啥我的 H.264 视频的尺寸比浏览器窗口小,但仍有溢出?

点击链接打开一个新的浏览器窗口

浏览器的问题:每次打开一个新的网页都是弹出新的窗口,怎么设置以新的标签的方式打开?

Window.open 实现导航与打开窗口,导航到一个特定链接地址,也可以打开一个新的浏览器窗体

在 GWT 应用程序中打开新的浏览器窗口被阻止