angularelementref

Angular: How to handle a null ElementRef?


In an Angular component, I display real-time data in a very complex way that requires the use of ElementRef for various purposes supporting UI interaction.

this.elRef.nativeElement.querySelector('.my-element')

As a result, I am running into a few rare use cases when referencing an element this way throws a null error because the element is either not yet accessible in the DOM or had been previously removed due to real-time data updates inside an *ngFor.

To prevent errors, I am checking the native element for null:

if(this.elRef.nativeElement.querySelector('.my-elment') != null) {
  // reference or set style on this element
}

This works fine, but is there a better approach? I have wound up with a lot of these if statements throughout my component as a result.

I have made every effort to avoid touching the DOM and to avoid running into the possibility for an element to be null otherwise in my template, but I am stuck with some rare cases that are just unavoidable.

Any advice greatly appreciated.


Solution

  • If at all possible, try to eliminate or minimize the use of ElementRef. The ElementRef docs state:

    Use this API as the last resort when direct access to DOM is needed. Use templating and data-binding provided by Angular instead. Alternatively you can take a look at Renderer2 which provides API that can safely be used even when direct access to native elements is not supported.

    Relying on direct DOM access creates tight coupling between your application and rendering layers which will make it impossible to separate the two and deploy your application into a web worker.

    If an ElementRef is unavoidable and there are cases where the ElementRef will be null, then the best you can do (without resorting to added complexity) is to use a little syntactic sugar and refactoring.

    1. Use a short variable reference

    const myEl = this.elRef.nativeElement.querySelector('.my-elment');
        
    if (myEl != null) { }
    

    2. Use a notNull() function to make code cleaner and refactor logic that requires the ElementRef into a subroutine.

    export function notNull(x: any): boolean {
      return x != null
    }
    
    
    const myEl = this.elRef.nativeElement.querySelector('.my-elment');
        
    notNull(myEl) ? doSomething(myEl) : false;