angular docs。
ViewContainerRefを使用した動的ディレクティブがあります
@Directive({
selector: '[dynamicComponent]'
})
export class DynamicComponentDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
コンポーネントコードからの抜粋
@ViewChild(DynamicComponentDirective) adHost: DynamicComponentDirective;
..
ngAfterViewInit() {
let componentFactory = null;
console.log(component);
componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
// this.adHost.viewContainerRef.clear();
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.createComponent(componentFactory);
}
最後に追加された<ng-template dynamicComponent></ng-template>
テンプレート内
このアプローチを取ることができます:ディレクティブを作成せず、代わりにng-template
にIDを指定します
<ng-template #dynamicComponent></ng-template>
コンポーネントクラス内で@ViewChild
デコレータを使用する
@ViewChild('dynamicComponent', { read: ViewContainerRef }) myRef
ngAfterViewInit() {
const factory = this.componentFactoryResolver.resolveComponentFactory(component);
const ref = this.myRef.createComponent(factory);
ref.changeDetectorRef.detectChanges();
}
私も同じ問題を抱えていました。ディレクティブをAppModuleに追加する必要があります。
@NgModule({
declarations: [
AppComponent,
...,
YourDirective,
],
imports: [
...
],
providers: [...],
bootstrap: [AppComponent],
entryComponents: [components to inject if required]
})
Angular 8では、私の修正は:
@ViewChild('dynamicComponent', {static: true, read: ViewContainerRef}) container: ViewContainerRef;
ディレクティブが構築されない場合、このエラーが表示されます。ディレクティブのコンストラクターにブレークポイントを設定し、ブレークポイントがヒットするかどうかを確認できます。そうでない場合、それはディレクティブを正しくロードしていないことを意味します。次に、ディレクティブを読み込んでいるコンポーネントがディレクティブをテンプレートに適切に追加していることを確認できます。
ディレクティブセレクター(この場合はdynamicComponent)が次の場所にある場合、同じ問題が発生することに注意してください。
コンポーネントの最初の要素
* ngIf条件の親要素
したがって、条件が一致する場合にのみ、コンポーネントhtmlの非ルートタグ内に配置して、viewContainerRefにコンポーネントをロードすることで、これを回避します。
また、viewRef
(この例ではdynamicComponent
)のセレクターが、componentFactoryResolver
を使用するコンポーネントのテンプレートで指定されたセレクターと一致しないことが問題である可能性があります。