【问题标题】:Angular Material Routed Dialog with Routed Tabs带有路由选项卡的 Angular Material Routed 对话框
【发布时间】:2020-08-17 18:07:09
【问题描述】:

开始:我的StackBlitz 包含我要解决的确切情况。

就像标题说的那样,我有一个路由对话框(基于路由打开的对话框),在这个对话框中我想要一个选项卡控件。每个选项卡也应该绑定到一个路由,所以我认为我的对话框也应该以某种方式获得<router-outlet/>

但是当我添加这个额外的 <router-outlet/> 而没有 name 参数时,渲染(我认为)变得疯狂 -> 结果:应用程序无响应。

当我添加名称参数并配置路由时,它也不起作用。

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'home', component: HomeComponent, children: [
    {path: 'dialog', component: DialogWrapperComponent},
    {path: 'routed-dialog',
     children: [
       {path: '', component: RoutedDialogWrapperComponent},
       {path: 'first', component: FirstComponent 
          //, outlet:'test' // Adding this does not work
       }
     ]
    }
  ]},
]

所以,RoutedDialogWrapperComponent 看起来像这样:

import { Component } from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { RoutedDialogComponent } from "./routed-dialog.component";
import { Router, ActivatedRoute } from "@angular/router";

@Component({
  template:''
})
export class RoutedDialogWrapperComponent{
  constructor(private dialog:MatDialog, private router:Router,
    private route: ActivatedRoute){
    this.openDialog();
  }

  private openDialog(){
    let dialog = this.dialog.open(RoutedDialogComponent);

    dialog.afterClosed().subscribe(result => {
      this.router.navigate(['../'],
        {
          relativeTo: this.route
        });
    });
  }
}

RoutedDialogComponent 的 HTML 如下:

<nav mat-tab-nav-bar>
  <a mat-tab-link routerLink="/home/dialog2/first">First</a>
  <a mat-tab-link>Second</a>
  <a mat-tab-link>Third</a>
</nav>

<!-- without name it rendering goes wild and will hang -->
<router-outlet name='test'></router-outlet>

<!-- this router-outlet does not work ... -->
<!-- 
  <router-outlet></router-outlet>
-->

最后我想有一个类似的 url:'/home/routed-dialog/first' 和 inside 对话框,在 tab-nav 下,我想看到 FirstComponent但我不知道如何...

其他情况,例如“激活”正确的选项卡,我有足够的信心来解决,但在这方面我需要一些帮助,因为我的 Angular 知识(就像它的俚语一样)非常有限 :-)

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    您可以在此处'router-outlet' in MatDialog is not working in Angular 7找到带有命名路由器插座的解决方案

    但是,如果您真的想要没有像/routed-dialog(popupContent:first) 这样的奇怪结构的干净链接,那么您可以执行以下技巧:

    • 将所有选项卡式组件定义为RoutedDialogWrapperComponent 的子级:

      {
        path: "routed-dialog",
        component: RoutedDialogWrapperComponent,
        children: [
          {
            path: "first",
            component: FirstComponent
          },
          {
            path: "second",
            component: SecondComponent
          },
          {
            path: "third",
            component: ThirdComponent
          },
          {
            path: '**',
            redirectTo: 'first'
          }
        ],
      }
      
    • &lt;router-outlet&gt; 放入RoutedDialogWrapperComponent 的模板中,并用&lt;ng-template&gt; 包裹起来

      <ng-template>
        <router-outlet></router-outlet>
      </ng-template>
      
    • 在组件类中获取对该包装器的引用:

      export class RoutedDialogWrapperComponent {
        @ViewChild(TemplateRef, { static: true }) templateRef: TemplateRef<any>;
      
    • 将该引用传递给RoutedDialogComponent

      export class RoutedDialogWrapperComponent implement OnInit {
         ngOnInit() {
           this.openDialog();
         }
      
         private openDialog() {
           const dialog = this.dialog.open(RoutedDialogComponent);
           dialog.componentInstance.contentTemplate = this.templateRef;
           ...
         }
      }
      
    • 最后,在RoutedDialogComponent内渲染:

      <nav mat-tab-nav-bar>
        <a mat-tab-link routerLink="home/routed-dialog/first">First</a>
        <a mat-tab-link routerLink="home/routed-dialog/second">Second</a>
        <a mat-tab-link routerLink="home/routed-dialog/third">Third</a>
      </nav>
      
      <ng-template [ngTemplateOutlet]="contentTemplate"></ng-template>
      

    Forked Stackblitz

    【讨论】:

    • 哇,太好了!非常感谢您的帮助!您对这样的解决方案有何感想?您认为这是一个好方法吗?我刚开始使用 Angular 进行开发,但 ViewChild 对我来说感觉很奇怪,这种感觉对吗?
    • 是的,我同意它看起来有点老套。但是在路由组件中打开对话框已经是为特定路由器打开对话框的 hacky 解决方案。此外,材料代码库在某些组件中使用了类似的方法,以便将 ng-content 移植到不同的地方 github.com/angular/components/blob/…
    • 我明白了...不过,我不太介意 ng-content 解决方案。否则你会怎么做?完全离开特定路由器的对话框并在主视图中打开该组件?
    • 不管你在哪里打开对话框,但是如果你打破这个链,路由器出口严重依赖父子上下文(不要在父路由组件中包含&lt;router-outlet&gt;),那么只有一个解决方案是使用命名的网点。
    猜你喜欢
    • 2019-10-22
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    相关资源
    最近更新 更多