我正在尝试在任务完成后提供警报 - 用户当时可能处于多个页面中的任何一个页面。警报应显示在所有页面上。
我正在使用实施BehaviorSubject
的服务
我的app.component.ts页面中的提供程序 - 单个实例
在我的app.component.html中,我有两个组件,一个是警报,另一个是触发警报。
<alert></alert>
<submit-service></submit-service>
服务发送到呈现警报的警报组件。 这工作正常,但只在提交服务的页面上(而不是任何其他页面) - 提交功能也在警报组件中。
submit-service
利用
public emit: BehaviorSubject<model> = new BehaviorSubject(new model());
一旦事件完成,它就会触发this.emit.next(_model);
在警报组件中,我订阅了事件
ngOnInit(): void {
this.service.emit.subscribe(data=> {
this.fireAlert(data);
}
});
}
所以我想主要的问题是,如何跨多个页面跨多个实例订阅单个服务?
编辑1
歧义的道歉,页面我的意思是单独的浏览器窗口或标签,即window.open
答案 0 :(得分:8)
以防其他人遇到同样的问题 - 实际上有一个答案。 使用全局存储事件可以跨所有浏览器选项卡/窗口遍历信息。
在服务中而不是使用BehaviourSubject
,服务将数据更新或“发送”到本地存储项,然后使用HostListener()
装饰器的事件监听器可以监听这些udpates - 它们可以监听所有窗口和标签。
示例:
@HostListener('window:storage', ['$event'])
onStorageChange(ev: StorageEvent) {
console.log(ev.key);
console.log(ev.newValue);
}
有关详细信息,请参阅此处:Storage events
答案 1 :(得分:0)
所以这里有几件事情在发挥作用。第一个是让您的应用程序知道是时候显示警报的服务。听起来你已经有了这个,但为了简单起见,我会确保你在forRoot()
上下文中声明这一点。我不会详细介绍有关此主题的详细信息,但实质上您需要确保您的服务在根上下文中运行。如果您开始延迟加载模块,然后从延迟加载的模块中订阅您的服务,它将创建它自己的依赖注入上下文,您将开始在桌子上敲击您想知道您的服务未更新的原因。 (去过那里:)
接下来要查看的是您要呈现警报的位置。您可能希望使用ComponentFactoryResolver
在您认为合理的最高级别组件中呈现警报。基本上(如果我理解你的需要正确),你需要将它放在同一个组件中,或者更高,就像你想要提醒警报的所有页面一样。例如,我正在开发一个具有仪表板的应用程序,我们有一个ComponentFactoryResolver
,它可以呈现整个应用程序中可能需要的任何和所有模态。这允许我们使用与您一样激活模态的行为主题,从仪表板内的任何位置调用模态。 Here's a great article使用ComponentFactoryResolver
。
更新1
因此,在意识到“页面”实际上是一个新的浏览器窗口后,这种方法不一定有效。使用BehaviorSubjects只会在应用程序上下文中更新,因此打开一个新窗口会创建一个新的应用程序上下文,即杀死BehaviorSubject
成为可行的候选者以使其工作。您需要拥有非特定于实例的服务。您提到的Web套接字将是一个不错的选择。
值得注意的是,如果可以重构代码以打开模态而不是新窗口,则可以维护依赖注入树的完整性,然后使用BehaviorSubjects来实现此目的。否则,你需要在应用程序之外保持状态的东西。