I have a directive that reads src attribute and appends a DynamicComponent. It also sets an input property of DynamicComponent.
@Directive({
selector: '[appDynamic]'
})
export class InjectDirective {
@ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef;
constructor(
private element: ElementRef,
private viewContainerRef: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver
) { }
ngOnInit(){
const nativeElement = this.element.nativeElement;
const src = nativeElement.getAttribute('src');
if (src) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(DynamicComponent);
const componentRef = this.viewContainerRef.createComponent(componentFactory);
componentRef.instance.mediaPath = src;
const parent = this.element.nativeElement.parentElement;
parent.insertBefore(componentRef.location.nativeElement, this.element.nativeElement.nextSibling)
}
}
}
The injection happens, but I can't read mediaPath in the DynamicComponent due to this not being set to the right value. this is an object that only has property __ngContext__.
export class DynamicComponent implements OnInit {
@Input() mediaPath:string;
constructor() { }
ngOnInit(): void {
}
openSection(event){ // click event
console.log(this); // this does not refer to instance of DynamicComponent
console.log(this.mediaPath); // this.mediaPath is undefined
}
}
What is the correct way of creating a component dynamically and also passing values to the component properties? I am using angular 11.
UPDATED to Angular 14. Still the same problem:
@Directive({
selector: '[appInject]'
})
export class InjectDirective {
@ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef;
constructor(
private element: ElementRef,
private viewContainerRef: ViewContainerRef,
) { }
ngOnInit(){
const nativeElement = this.element.nativeElement;
const src = nativeElement.getAttribute('src');
if (src) {
const componentRef = this.viewContainerRef.createComponent(DynamicComponent);
componentRef.setInput("mediaPath",src)
const parent = this.element.nativeElement.parentElement;
parent.insertBefore(componentRef.location.nativeElement, this.element.nativeElement.nextSibling)
}
}
}
export class DynamicComponent implements OnInit {
@Input() mediaPath:string;
constructor() { }
ngOnInit(): void {}
openFindSimilarSection(event){
console.log(this); // only has __ngContext__ property
console.log(this.mediaPath); // this is undefined
}
}
//used like this:
<img [src]="dynamically.added.path" appInjectFindSimilar>
openFindSimilarSection?