1

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?

Community
  • 1
  • 1
user776686
  • 7,933
  • 14
  • 71
  • 124
  • I guess `resize` is fired already before `sidebar` is set. You subscribe in `ngOnInit()` but `sidebar` will only be available in the later `ngAfterViewInit()` – Günter Zöchbauer Jan 31 '17 at 09:46
  • It doesn't seem to matter. When I subscribe in `ngAfterViewInit` or even in `ngAfterContentInit` - the result is the same. – user776686 Jan 31 '17 at 09:49

1 Answers1

4

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);
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567