What is the best way to address elements that are affected by a wrong *ngIf condition at the beginning?

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'".

Answer №1

TemplateType should be set in the ngOnInit lifecycle hook before accessing any DOM elements. Avoid modifying element states in the ngAfterViewInit method and there is no need to manually trigger

this.changeDetector.detectChanges();


ngOnInit(): void{ 
 this.TemplateType = this.determineElementType(); 
 if(this.ElementData.selfClosing){
    this.ForgedElement = this.buildElement();
    this.TemplateType = 'single element';
  }
}

ngAfterViewInit(): void{ this.initGraphic(); }

private initGraphic():void{
    if(!this.ElementData.selfClosing && this.TemplateType !== undefined){
      console.log(this.TemplateType);
      this.applyElementProperties();
    } else { 
      console.log('GRRRRRRRR!!!!!!!'); 
    }    
 }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using *ngFor and [(ngModel)] simultaneously in Angular2 and Ionic2

Is there a way to combine *ngFor and [(ngModel)] in order to dynamically update data in a list? Here's a straightforward code snippet for reference: <ion-item *ngFor="let item of items" [(ngModel)]="item.title"> {{item.title}} </ion-item&g ...

Guide to sending a generic to a React component and leveraging its power within the component

I am currently working on developing an input component that requires a displayName as a string and a value as a generic type. Additionally, it needs to take a function as a prop that will be triggered to handle the value when the input changes. For examp ...

Executing observables sequentially based on their dependencies

Looking for guidance on how to accomplish the task mentioned in the title. Here's my situation. I have three methods in my service: isUserEnable(), isLicenseStatusEnable(), and resetPassword(), which need to be executed sequentially. Firstly, I must e ...

When employing TypeScript, an error pops up stating "cannot find name 'ObjectConstructor'" when attempting to use Object.assign

I am rephrasing my query as I realized it was unclear earlier. I have an API that is sending me data in the following format: {"photos":[{"id":1,"title":"photo_1_title"}]} In my code, I have a variable called photos and a function named getPhotos() For ...

"Unlocking the Secrets: Mastering Step Index Manipulation in Angular Arch

Looking for tips on changing the step index in Angular Arch Wizard. I have two forms on the same page and need to navigate to a specific step. Any ideas? <aw-wizard > <aw-wizard-step > <form role="form" > < ...

Can you explain the significance of this particular line in the source code of VSCode?

While browsing through the VS Code source code, I stumbled upon the following snippet: https://github.com/microsoft/vscode/blob/5da4d93f579f3fadbaf835d79dc47d54c0d6b6b4/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts#L166 It appear ...

Leverage a provider implementation within another implementation of the same provider in Angular

Is it possible to inject one provider implementation into another implementation of the same provider in Angular? I have been unable to achieve this so far. The goal is to be able to customize the second implementation using data from the first implementat ...

Troubleshooting Angular AutoComplete's Lack of Response from Async Validator

I am looking to enhance the user experience by implementing autocomplete functionality that triggers an error and sets the FormControl to invalid when a user deletes a character from a selected value. Unfortunately, I have encountered difficulties in achie ...

Guide on exporting type definitions and utilizing them with npm link for a local package

I am in the process of developing a new testing tool called tepper as an alternative to supertest. My goal is to make this package available in both ESM and CJS formats. However, I'm encountering an issue where users of the library are unable to locat ...

Converting selected dates to Date Objects with Angular Bootstrap's ngbDatepicker

When using the Angular Bootstrap ngbDatepicker for a date field in a form, the code looks like this: <input ngbDatepicker #d="ngbDatepicker" [readonly]="true" [minDate]="{year: 1900, month: 1, day: 1}" ...

Tips for customizing Primeng's SplitButton to resemble a Bootstrap button styling

Hey there! I'm working on a project with a Primeng splitbutton and a Bootstrap button. You can check it out in the stackblitz link below: https://stackblitz.com/edit/angular6-primeng-hlxeod?file=src/app/app.component.html I'm having trouble cus ...

Navigating through arrays within a JSON object requires iterating over each array individually

My challenge is to iterate through multiple arrays within a json object. To give you a better understanding, here is an image of the json object's structure: https://i.sstatic.net/iMQDL.png I have attempted to iterate through it using ngFor, but I k ...

Tips on changing the date format in Typescript to the desired format

My date string reads as 2016-09-19T18:10:31+0100. Here's what I'm doing: let dateString:string = 2016-09-19T18:10:31+0100; let newDateString:Date = new Date(dateString); The output I'm currently getting is Tue Sep 19 2016 18:10:31 GMT+0530 ...

Express server crashes when incorporating TypeScript alongside CRA

Summary I recently implemented Typescript into a Create React App (CRA) project, but I keep encountering the following error when attempting to serve the built application: SyntaxError: path\to\root\server\loader.js: Unexpected token, ...

Conflicting events arising between the onMouseUp and onClick functions

I have a scrollbar on my page that I want to scroll by 40px when a button is clicked. Additionally, I want the scrolling to be continuous while holding down the same button. To achieve this functionality, I implemented an onClick event for a single 40px s ...

Angular app unit tests encountering issues due to Keycloak role-based redirection mechanism

In my Angular application, I needed to redirect users to either /route1 or /route2 based on their role. However, Keycloak only allows for a single route to be specified after logging in (in this case, route1). To solve this routing dilemma, I implemented t ...

Using *ngFor in TypeScript code

Hello there, I have a question about performing the logic of *ngFor in typescript. Is it possible to loop through data from my JSON API in the typescript file similar to how *ngFor works in HTML? Any guidance on this matter would be greatly appreciated. ...

Guide to recursively iterating through an array of objects in TypeScript/Javascript

In my current programming challenge, I am dealing with an array of objects that have two properties: target and source. Additionally, there is a designated starting source to begin with. The goal is to start from the starting source and recursively find a ...

Animating the Position of Masks using Angular 2+

I am encountering issues with animating the mask-position property using Angular's animation library and I am seeking assistance in identifying where my mistake lies. This method is successful: @keyframes maskWipe{ from {mask-position: 100% 0; ...

Verify the specific type conditions of a key value in a mapped type

I am attempting to achieve the following: If the actions property exists, and there are callbacks within the actions properties that return a string, then return X or Y. The above code is expressed as: // type MappedType<T> = { // [K in keyof T]: ...