1

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

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

要将许多组件发送到同一个组件,RouterOutlet我似乎必须将所有这些组件加载到定义插座的同一个父组件中;我不希望有这样一个单一的顶级组件。

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

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

不同的节点代表不同的应用特征,包含不同的实体类型。因此,树的各个节点都需要:

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

这是一个例子:

  • 约会
    • 乔上午 11 点
    • 凌晨 12 点苏
  • 人们
    • 乔·史密斯
    • 苏莉(选择)
      • 3天前
      • 5天前

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

我们目前正在使用我们的主要路线来操作这棵树。在渲染其可路由组件之前,我们调用CanActivate以等待子节点的数据被解析。然后我们在渲染后立即操作 DOM 将节点嫁接到树上。这棵树自己工作。我喜欢应用程序的主 URL 导航是由路由树驱动的。尽管我欢迎其他建议。

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

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

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

4

1 回答 1

1

这听起来与Angular 2 动态选项卡中使用的类似方法,用户单击选择的组件也会在这里有所帮助。

通过使用包装器元素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) {}
}
于 2016-05-05T11:04:22.577 回答