Search code examples
angulareventsviewchild

ViewChild does undefined during resize event


Let's see:

import {
  Component, OnInit, ViewEncapsulation, Input, ElementRef, ViewChild, AfterViewInit
} from '@angular/core';

@Component({
  selector: 'app-sidebar',
  template: `
  <aside #sidebar>
  Sidebar
  </aside>`,
})
export class AppSidebar implements OnInit, AfterViewInit {
  @ViewChild('sidebar')
  private sidebar: ElementRef;

  constructor() {
  }

  ngOnInit() {
    console.log('OnInit has:', this.sidebar)
    window.addEventListener('resize', this.resetSidebar);
  }

  ngAfterViewInit() {
    console.log('AfterViewInit has:', this.sidebar);
  }

  resetSidebar() {
    console.log(this.sidebar);
  }
}

this.sidebar is volatile here. It logs out correctly during the lifecycle hooks, but when you resize the window it becomes null. No camelCase problem, no conditional dom, so what's wrong with the code?


Solution

  • The problem is caused by how you register the event handlers.

    With

     window.addEventListener('resize', this.resetSidebar);
    

    this inside resetSidebar doesn't point to the AppSidebar class anymore.

    Use .bind(this) to ensure this keeps working

     window.addEventListener('resize', this.resetSidebar.bind(this);
    

    You can also use arrow functions https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

     window.addEventListener('resize', (event) => this.resetSidebar(event);