I'm trying to modify the attributes and styles of DOM elements that only appear once an *ngIf condition becomes true. I'm using @ViewChild() decorator to access these elements, but I keep running into an error:
Cannot read property nativeElement of undefined
I've read suggestions about using ChangeDetectorRef to manually update the component after toggling the variable that controls the DOM element's display. However, I haven't had success with this method either. The examples I found don't include {static: true} in their @viewChild() decorators, which made me wonder if there have been changes requiring a different approach or standard.
This is how my current code looks:
inside component
//Where data enters the component.
@Input() ElementData : OvaadGraphicObject;
TemplateType: string;
@ViewChild('graphicContainer', {static: true}) GraphicContainer: ElementRef;
//initialize the TemplateType variable
ngOnInit(): void{ this.TemplateType = this.determineElementType(); }
//modify DOM element after *ngIf condition is true and element exists
ngAfterViewInit(): void{ this.initGraphic(); }
/*Initializing the TemplateType var at different lifecycles to work in the proper order*/
private initGraphic():void{
if(this.ElementData.selfClosing){
this.ForgedElement = this.buildElement();
this.TemplateType = 'single element';
}
else{
this.changeDetector.detectChanges();//
if(this.TemplateType !== undefined){
console.log(this.TemplateType);
this.applyElementProperties();
}
else{ console.log('GRRRRRRRR!!!!!!!'); }
}
}
private applyElementProperties():void{
const attributes: OvaadGraphicAttribute[] = this.ElementData.attributes;
const styles: OvaadSvgStyleProperty[] = this.ElementData.styles;
if(attributes.length > 0){
attributes.forEach(a=>{
this.GraphicContainer.nativeElement.setAttribute(a.attribute, a.setting);
});
}
if(styles.length > 0){
styles.forEach(a=>{
this.GraphicContainer.nativeElement.style[a.property] = a.setting;
});
}
}
inside my template
<svg:g *ngIf="TemplateType === 'single element'" [innerHtml]='insertElement()'></svg:g>
<svg:g #graphicContainer *ngIf="TemplateType == 'group element'">
<svg:g svg-component *ngFor="let item of ElementData.subElements" [ElementData]="item"></svg:g>
</svg:g>
... (other similar DOM element rendering)
I'm using #graphicContainer on multiple items in the template. Although I thought it wouldn't cause any issues because only one of them would render due to *ngIf, removing all but one didn't change anything. How can I resolve this?
Update
To provide more context, here is what determineElementType() function looks like:
private determineElementType():string{
const item: string = this.ElementData.element;
let elementType: string;
//logic to determine the type based on input data
...
return elementType as string;
}
I could directly use *ngIf on the main data object accessed through @Input(), but this functionality isn't required in every case. In scenarios where it is needed, other tasks must be completed before toggling the element. That's why I'm taking this approach rather than just using *ngIf="ElementData.element === 'g'".