Ich habe versucht, eine Tab-Ansicht zu erstellen, und die Gedankenprojektion könnte ein guter Ansatz sein. Ich habe es von dieser article gelernt. Ich dachte, dass ich es dynamisch machen könnte, indem ich nur ein bestimmtes Array von Komponenten eingab und sie als die Seite für die ausgewählte Registerkarte angezeigt würden.Angular 2 - ContentChidren der übergeordneten Komponente sind nicht definiert, wenn die untergeordnete Komponente dynamisch erstellt wird.
Hier ist mein Versuch, dies zu tun:
@Component({
selector: 'my-app',
template:`
<h1>Experiments</h1>
<button class="add-button" (click)="add()">Add</button>`
})
export class App {
components:Array<any> = [PrepSetupTab,FinalizeTab]
constructor(private cdr: ChangeDetectorRef,
private compFR: ComponentFactoryResolver,
private viewContainer: ViewContainerRef){}
add():void{
var transTabRefs: Array<any>= []
this.components.forEach(tabComponent=>{
let compFactory = this.compFR.resolveComponentFactory(tabComponent);
let compRef = this.viewContainer.createComponent(compFactory);
let tabFactory = this.compFR.resolveComponentFactory(Tab);
let transcludedTabRef = this.viewContainer.createComponent(tabFactory,this.viewContainer.length - 1, undefined, [[compRef.location.nativeElement]]);
transTabRefs.push(transcludedTabRef.location.nativeElement);
})
let tabsFactory = this.compFR.resolveComponentFactory(Tabs); // notice this is the tabs not tab
this.viewContainer.createComponent(tabsFactory,0,undefined,[transTabRefs]);
}
}
Randnotiz, add() als ein Klick-Handler-Taste ist nicht beabsichtigt, Funktionalität andere diese Fehler zu vermeiden: "EXCEPTION: Expression has changed after it was checked"
. Ich bekomme diesen Fehler, wenn ich ihn in irgendeinen Lebenszyklus-Haken stecke. Obwohl das eine Herausforderung ist, mit der ich mich später befassen muss.
Also im Grunde ich die einzelnen Komponenten im Array erstellen, und dann stecke ich sie als ng-Inhalt für jede erstellte Registerkarte Komponente. Dann nimm jede Tab-Komponente und stecke sie in ng-content für Tabs Component.
Das Problem ist Tabs Component findet nicht die contentChildren der dynamisch erstellten Tab Kinder. Hier ist der Code für die Tabs-Komponente, in der die untergeordneten Inhalte nicht definiert sind.
@Component({
selector: 'tabs',
template:`
<ul class="nav nav-tabs">
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
<a>{{tab.title}}</a>
</li>
</ul>
<ng-content></ng-content>
`
})
export class Tabs implements AfterContentInit {
@ContentChildren(Tab) tabs: QueryList<Tab>;
// contentChildren are set
ngAfterContentInit() {
// get all active tabs
let activeTabs = this.tabs.filter((tab)=>tab.active);
// if there is no active tab set, activate the first
if(activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: Tab){
// deactivate all tabs
this.tabs.toArray().forEach(tab => tab.active = false);
// activate the tab the user has clicked on.
tab.active = true;
}
}
Es scheint ziemlich klar zu mir zu sein, dass die Tab-Komponente dann zu einem anderen Zeitpunkt erstellt, wenn ich sich als Inhalt Kinder aus der Tabs Komponente zugreifen muß. Ich habe auch versucht, die ChangeDetectionRef.changeDetect(), aber das hilft nicht.
Vielleicht macht dies alles durch Content-Projektion ist nicht der einfachste Weg oder am besten, so dass ich für Vorschläge offen bin. Hier ist die plunk, danke!
'@ ContentChildren' nicht mit dynamischer Erstellung Komponente arbeiten. Das ist per Entwurf – yurzui
http://plnkr.co/edit/t1GnzDDR2s5g8PSDojXv?p=preview – yurzui
Wow, InitContent Ich habe das vorher nicht gesehen! Und wenn Sie daran denken, werden Sie vielleicht etwas von diesem Code erkennen, da ich denke, dass ich es von einem früheren Plunk bekommen habe :). –