问题描述
我们正在建设一个浏览树的角2的应用(上左),和相邻的详细信息窗格(右侧)。
我要呈现在同一个细节面积约20-30成分不同,取决于所选的树是什么节点。
发送许多组件相同的 RouterOutlet
看来我必须加载,其中出口是指在同一个父组件所有这些组件;我想preFER不要有这样的单片顶级组件。
在说不清楚的情况下,这剩下的更详细地介绍我的情况,然后再重申在年底同样的问题。
树只能有一次选择的一个节点。当选择一个节点,所有其他非父节点被关闭,和儿童选定节点的列表中被装载在网络和显示所选择的节点的下方。与所选择的节点的详细信息还装载通过网络,并在共享右窗格区呈现,替换为pviously那里显示。$ P $任何其它信息
不同节点重新present不同的应用特点和包含不同的实体类型。因此,树的各个节点处同时需要:
- 不同的子模板/组件展开子树(有些树节点枚举联系人姓名,其他包含约会,等等。)
- 不同的模板/组件
在详细信息窗格加载
下面是一个例子:
- 约会
- 乔上午11点
- 苏上午12点
- 人
- 张三
- 苏阿里的(选择)
- 4天前
- 4天前
详细信息面板会显示有关苏阿里的信息。
我们正在用我们的主要途径操作树。我们称之为 CanActivate
来等待子节点的数据呈现其可路由组件之前得到解决。然后我们操作DOM接枝在其上呈现后立即树的节点。树的作品本身。我喜欢这样,我会由路径树预计,应用程序的主网址导航被驱动;虽然我欢迎替代建议。
我们是的尝试的使用辅助路线,以显示正确的详细信息窗格的模板。有关树节点了解如何使用简单的辅助路线启动正确的详细信息窗格。但是,我们有两个问题:
-
辅助路线不支持
CanActivate
,所以直到@Resolve
装饰在角可用2,我们不能轻易延迟渲染辅助组件,直到数据被解决。这是一个低优先级的问题,因为这将是固定的角释放 -
所有的细节辅助组件必须在一个父组件加载,这样他们就可以覆盖每一个相同的父辅助
RouterOutlet
。是否有另一种方式来做到这一点,并不需要如此大规模的顶级组件?
这听起来像一个类似的方法在使用Angular 2动态的卡口与用户单击选择组件将有助于在这里。
通过使用包装元素周围 ViewContainerRef.createComponent()
(原 DynamicComponentLoader.loadXxx()
您可以添加通过这使得取决于它被传递的数据(例如一个共享服务)的组件的列表的路由器一个主分量
@Component({
选择:DCL-包装',
模板:`< DIV#靶GT;< / DIV>`
})
出口类DclWrapper {
@ViewChild(目标,{阅读:ViewContainerRef})的目标;
@input()型;
厘米preF:ComponentRef;
私人isViewInitialized:布尔= FALSE; 构造函数(私人解析:ComponentResolver){} updateComponent(){
如果(!this.isViewInitialized){
返回;
}
如果(this.cm preF){
this.cm pref.destroy();
}
this.resolver.resolveComponent(this.type)。然后((工厂:ComponentFactory<&任何GT)=> {
this.cm preF = this.target.createComponent(厂)
});
} ngOnChanges(){
this.updateComponent();
} ngAfterViewInit(){
this.isViewInitialized = TRUE;
this.updateComponent();
} ngOnDestroy(){
如果(this.cm preF){
this.cm pref.destroy();
}
}
}
打造子组件列表像
@Component({
选择:插入逐个路由器',
指令:[DclWrapper]
模板:`< DCL-包装* ngFor =让键入sharedService.types[类型] =输入>< / DCL-包装>`})
出口类InsertedByRouter {
构造函数(私人sharedService.types){}
}
We're building an Angular 2 application with a navigable tree (on the left), and an adjacent detail pane (on the right).
I want to render about 20-30 different components in the same detail area, depending on what node on the tree is selected.
To send many components to the same RouterOutlet
it seems I have to load all those components in the same parent component where the outlet is defined; I'd prefer not to have a monolithic top-level component like that.
In case that isn't clear, the rest of this describes in more detail my scenario, and then restates the same question at the end.
The tree can only have one node selected at a time. When a node is selected, all other non-parent nodes are closed, and the list of children for the selected node are loaded over the network and display beneath the selected node. The detail information related to the selected node is also loaded over the network, and rendered in the shared right pane area, replacing any other information that was previously displayed there.
Different nodes represent different application features and contain different entity types. Therefore, various nodes of the tree require both:
- different child templates/components to expand the child tree (some tree nodes enumerate contact names, others contain appointments, etc.)
- different templates/components loaded in the detail pane
Here is an example:
- appointments
- Joe 11am
- Sue 12am
- people
- Joe Smith
- Sue Li (selected)
- 3 days ago
- 5 days ago
The detail panel would show information about Sue Li.
We are currently using our Primary Routes to operate the tree. We call CanActivate
to wait for the child node's data to be resolved before rendering its Routable Component. Then we manipulate the DOM to graft the node on the tree immediately after it is rendered. The tree works by itself. I like that the application's main URL navigation is driven as I'd expect by the route tree; although I'd welcome alternate suggestions.
We are attempting to use Aux Routes to display the correct detail pane template. The relevant tree nodes understand how to "initiate" the correct detail pane using a simple Aux Route. However, we have two problems:
Aux Routes don't support
CanActivate
, so until the@Resolve
decorator is available in Angular 2, we can't easily delay render for Aux Components until data is resolved. This is a low-priority issue, since it will be fixed with the Angular release.All the detail Aux Components must be loaded in one parent component, so they can each overwrite the same parent Aux
RouterOutlet
. Is there another way to do this that doesn't require such a massive top-level component?
This sounds like a similar approach as used in Angular 2 dynamic tabs with user-click chosen components would help here as well.
By using a wrapper element around ViewContainerRef.createComponent()
(former DynamicComponentLoader.loadXxx()
you can add one main component by the router which renders a list of components depending on data it gets passed (from a shared service for example)
@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();
}
}
}
to build the list of child components like
@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) {}
}
这篇关于(可路由组件)与相邻的详细信息窗格的数据树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!