(Routable Component)具有相邻详细信息窗格的数据树

时间:2016-05-05 05:38:11

标签: angularjs angular angular-component-router

我们正在使用可导航树(左侧)和相邻的详细信息窗格(右侧)构建Angular 2应用程序。

我想在同一个细节区域渲染大约20-30个不同的组件,具体取决于树上选择的节点。

要将多个组件发送到同一个RouterOutlet,我似乎必须在定义出口的同一父组件中加载所有这些组件;我不希望有像这样的单片顶层组件。

如果不清楚,其余部分将更详细地描述我的场景,然后在最后重述相同的问题。

树一次只能选择一个节点。选择节点后,将关闭所有其他非父节点,并通过网络加载所选节点的子节点列表,并显示在所选节点下方。与所选节点相关的详细信息也会通过网络加载,并在共享的右窗格区域中呈现,替换之前在那里显示的任何其他信息。

不同的节点表示不同的应用程序功能并包含不同的实体类型。因此,树的各个节点都需要:

  • 用于展开子树的不同子模板/组件(某些树节点枚举联系人姓名,其他包含约会等)。
  • 详细信息窗格中加载的不同模板/组件

以下是一个例子:

  • 约会
    • 乔上午11点
    • Sue 12am
    • Joe Smith
    • Sue Li (已选中)
      • 3天前
      • 5天前

详情面板将显示有关Sue Li的信息。

我们目前正在使用主路由来运行树。我们调用CanActivate等待子节点的数据在呈现其Routable组件之前被解析。然后我们操作DOM以在渲染后立即在树上移植节点。这棵树独自工作。我喜欢应用程序的主要URL导航是由路由树所期望的那样驱动的;虽然我欢迎其他建议。

我们尝试使用Aux Routes来显示正确的详细信息窗格模板。相关的树节点了解如何启动"使用简单的辅助路线的正确细节窗格。但是,我们有两个问题:

  1. Aux Routes不支持CanActivate,因此在Angular 2中提供@Resolve装饰器之前,我们无法轻易延迟Aux组件的渲染,直到数据为止解决。这是一个低优先级的问题,因为它将通过Angular版本修复。

  2. 所有细节Aux组件必须加载到一个父组件中,因此它们每个都可以覆盖相同的父Aux RouterOutlet。还有另一种方法可以做到这一点并不需要如此庞大的顶级组件吗?

1 个答案:

答案 0 :(得分:1)

这听起来像Angular 2 dynamic tabs with user-click chosen components中使用的类似方法也会有所帮助。

通过在ViewContainerRef.createComponent()(前DynamicComponentLoader.loadXxx()周围使用包装元素,您可以通过路由器添加一个主要组件,该组件根据传递的数据呈现组件列表(例如,来自共享服务)

@Component({
  selector: 'dcl-wrapper',
  template: `<div #target></div>`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() type;
  cmpRef:ComponentRef;
  private isViewInitialized:boolean = false;

  constructor(private resolver: ComponentResolver) {}

  updateComponent() {
    if(!this.isViewInitialized) {
      return;
    }
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
   this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
      this.cmpRef = this.target.createComponent(factory)
    });
  }

  ngOnChanges() {
    this.updateComponent();
  }

  ngAfterViewInit() {
    this.isViewInitialized = true;
    this.updateComponent();  
  }

  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }
}

构建子组件列表,如

@Component({
  selector: 'inserted-by-router',
  directives: [DclWrapper],
  template: `<dcl-wrapper *ngFor="let type in sharedService.types" [type]="type"></dcl-wrapper>`})
export class InsertedByRouter {
  constructor(private sharedService.types) {}
}