Следуя идеям Юрзуи, вот как я могу их применить:
Здесь - это пример StackBlitz .
changeDetectorRef.detectChanges()
showContent () {
this.showPanel = !this.showPanel;
if (this.showPanel) {
this.cdr.detectChanges();
this.loadComponent();
}
}
сеттер для ViewChild
private _ref: ViewContainerRef;
private get ref () {
return this._ref;
}
@ViewChild('ref', { static: false, read: ViewContainerRef })
private set ref (r) {
console.log('setting ref', r)
this._ref = r;
if (this._ref) {
this.loadComponent();
}
}
showPanel = false;
constructor (
private cdr: ChangeDetectorRef,
private cfr: ComponentFactoryResolver,
) { }
loadComponent () {
const factory = this.cfr.resolveComponentFactory(ChildComponent);
const component = this.ref.createComponent(factory);
}
showContent () {
this.showPanel = !this.showPanel;
}
с использованием <ng-container>
Как вы указали, использование ngTemplateOutlet
обычно является хорошим решением, нокогда вы имеете дело с более чем одним компонентом, выполнение всей этой логики в шаблоне может быть затруднительным.
Мы можем использовать API ViewContainerRef
для обработки всего из вашего компонента(.ts file
).
<button (click)="showContent()">Show Panel</button>
<ng-container #vcr></ng-container>
@ViewChild('vcr', { static: true, read: ViewContainerRef })
vcr: ViewContainerRef;
showContent () {
this.showPanel = !this.showPanel;
this.showPanel && this.attachComponent();
!this.showPanel && this.removeComponent();
}
private attachComponent () {
const compFactory = this.cfr.resolveComponentFactory(ChildComponent);
const compView = this.vcr.createComponent(compFactory);
}
private removeComponent () {
this.vcr.clear();
}
Этот подход дает вам больший контроль, чем вы можете справиться!
Например, вы можете сохранить состояние компонента после того, как showPanel
станет ложным с помощьюиспользуя vcr.detach
и vcr.insert
.
Вы можете найти, как прямо здесь .