【问题标题】:How to open a Angular component in a new tab?如何在新选项卡中打开 Angular 组件?
【发布时间】:2019-01-30 23:21:55
【问题描述】:

我有大量数据要显示在屏幕上。我需要提供一个简化列表,以便用户可以选择其中一项并查看其详细信息。

假设我有一个组件 SimpleListComponent,它将保存数据并呈现一个简化的视图

export class SimpleListComponent{
    @Input() data: any[];
}

html

<ul>
    <li *ngFor="let item of data">
        <a>{{item.name}}</a>
    </li>
</ul>

用户应该能够点击其中一个项目并在新选项卡中打开包含该项目详细信息的视图。 所以如果我有第二个组件

export class DetailedViewComponent{
    @Input() item: any;
}
<div>
    <!--All fields of item here-->
</div>

编辑:这里的问题是我正在呈现来自非常定制的搜索的数据,因此我没有 ID 来从服务器获取详细信息或任何其他方式来再次获取数据。所以唯一的方法就是以某种方式传递已经加载的数据。

我怎样才能在角度上实现这一点?将项目数据提供给第二个组件并在新选项卡中打开它?

【问题讨论】:

  • target="blank" on link 或其他
  • 例如:window.open('/login', '_blank'),如果你想从 .ts 打开
  • 您是指新的浏览器标签,还是网页中的某种新的 HTML 标签?当然,在同一个 Angular 应用程序上打开两个浏览器选项卡是可能的,但是如果您需要它们相互交互,这会增加很多复杂性——因此在您的页面中引入某种虚拟选项卡可能会更好。
  • @MarkHughes 感谢您的评论。所以这将是浏览器中的一个新选项卡,但我不需要绑定数据或任何涉及选项卡之间交互的东西。这只是为了以更清晰的视图呈现数据。我想我可以通过 target="_blank" 实现这一点,但我不确定如何将我的项目传递给新组件
  • 你不能轻易地在浏览器标签之间传递这样的东西。有一些方法可以做到这一点,但我主要称它们为黑客......所以你的新标签需要从服务器加载它需要的数据。如果页面中有“虚拟选项卡”,则可以传递整个对象 - 交叉选项卡部分使这变得更加困难。

标签: angular typescript angular2-components


【解决方案1】:

我知道这是一篇旧帖子,但由于这是您搜索“如何在新选项卡/窗口中打开角度组件”时的第一个结果,所以我想发布一个答案。

如果您为组件创建路由并在新选项卡中加载路由,您最终将再次引导应用程序。

因此,如果您想在不引导整个应用程序的情况下打开 Angular 组件,您可以使用 Angular 门户来实现。您还可以轻松地在父窗口和子窗口之间传递数据。

我最近有这个需求,但我找不到任何全面的资源,所以我整理了一篇关于它的文章。

https://medium.com/@saranya.thangaraj/open-angular-component-in-a-new-tab-without-bootstrapping-the-whole-app-again-e329af460e92?sk=21f3dd2f025657985b88d6c5134badfc

这是示例应用的现场演示

https://stackblitz.com/edit/portal-simple

【讨论】:

  • 我将关注提供的文章,这听起来很有希望。如果有效,则应将答案标记为正确。
  • 如果用户想通过提供此 url 直接在浏览器中导航到 portal-simple.stackblitz.io/assets/modal/popout.html 会发生什么?
  • popout.html 是一个空白的 html 页面。如果您直接转到该 html,它将是空白的。这仅适用于您已经加载了 Angular 应用程序并且您希望通过单击链接或按钮而不是直接更改 url 在子浏览器选项卡中打开另一个组件的情况。
  • 那么,直接导航是不可能的?
  • 我喜欢你的想法。我正在从事的项目中有这个要求。我唯一不喜欢的是每次我希望能够在新窗口中打开一个新组件时需要更改多少。我进行了一些更改以使服务更通用,因此可以弹出任何条目组件,而无需对服务或令牌进行修改(除了您的弹出模式枚举,但这只是您想要的)。这是链接:stackblitz.com/edit/angular-portal-poc
【解决方案2】:

您可以为DetailedViewComponent和“”创建路由

在您的路由中:

{
    path: 'detailed/:id',
    component: DetailedViewComponent
}

然后在 SimpleListComponent 的 typeScript 上:

public detailedPath;
ngOnInit() {
     this.detailedPath = window.location.origin + '/detailed/';
}

在您的 SimpleListComponent 的 Html 中:

<ul>
   <li *ngFor="let item of data">
      <a href="{{detailedPath + item.id}}" target="_blank">
   </li>
</ul>

在DetailedViewComponent的TypeStript上:

public id;
constructor(private routeParams: ActivatedRoute) {
}

ngOnInit() {
    this.routeParams.params.subscribe(params => {
      this.id = parseInt(params['id']);
    });
    //Some logic to get the details of this id
}

【讨论】:

  • 您能解释一下为什么DetailedViewComponent 会在新标签页中打开吗?您的代码示例中的具体内容是什么?
  • 这是否适用于具有DetailedViewComponent 的延迟加载模块?
【解决方案3】:

如果有人遇到与我相同的问题:

我结束了使用localstorage 来临时存储我的对象并从另一个窗口访问它。

所以代码最终是这样的:

<a target="_blank" [routerLink]="['/details', item.name]" click="passObject(item.name)">
passObject(i){
    localStorage.setItem('i.name', JSON.stringify(i));
}

在细节组件中:

ngOnInit() {
    this.item = JSON.parse(localStorage.getItem(param));
}

我可以尝试的另一个想法是实现message service

【讨论】:

  • 任何使用这种方法的人请注意,浏览器对可以存储在本地存储中的对象的长度有限制。 OP 说他们有“大量的数据要显示”,所以我不认为这是一个正确的解决方案。消息服务的第二个示例也不起作用,因为该服务不是跨选项卡共享的。
【解决方案4】:

我建议你从 HTML 中使用 target 属性:

&lt;a target="_blank" [routerLink]="['/detail',item.name]"&gt;

在这个例子中,“/item/:name”应该在你的路由模块中定义。

【讨论】:

  • 我看到 /detail 然后会路由到我的DetailedViewComponent,但我需要传递整个项目,而不仅仅是名称。对不起,如果我误解了你的问题
  • 您将前往另一条路线。在此页面上,您可以使用解析器执行 HTTP GET 并获取请求的信息。 Alligator.io 的示例alligator.io/angular/route-resolvers 如果这仍然不清楚,请告诉我,我将创建一个示例。
  • 现在清楚了,你的回答很有道理,是我的问题不清楚。
猜你喜欢
  • 1970-01-01
  • 2020-10-09
  • 2021-12-02
  • 1970-01-01
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
相关资源
最近更新 更多