Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why @ViewChild(NgbDropdown) not working in my component?

I want to extend ng-Boostrap's dropdown feature, to close the menu by pressing the browsers back button (on mobile). But this.dropdown is undefined in hide function. Why?

import {Component, Input, ViewChild} from '@angular/core';
import {NgbDropdown} from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-mobile-dropdown',
  templat: '<div ngbDropdown class="menu" [placement]="placement" (openChange)="openChange($event)">
  <span class="menu-btn" ngbDropdownToggle><i [class]="btnIcon"></i><span *ngIf="btnLabel">{{btnLabel}}</span></span>
  <div ngbDropdownMenu>
    <a ngbDropdownItem *ngFor="let item of actions" class="dropdown-item" (click)="item.action()">{{item.label}}</a>
  </div>
</div>
'
})
export class MobileDropdownComponent{

  @ViewChild(NgbDropdown,{static:false}) dropdown: NgbDropdown;
  @Input() placement: string;
  @Input() btnIcon: string;
  @Input() btnLabel: string;
  @Input() actions: Array<any>;

  hide(){
    console.log('closing', this.dropdown);
    window.removeEventListener('popstate', this.hide);
    this.dropdown.close();
  }

  openChange(opened: boolean) {
    if (opened) {
      window.history.pushState('ddOpen',null,null);
      window.addEventListener('popstate',this.hide);
    } else {
      if(history.state === 'ddOpen'){
        window.history.back();
        window.removeEventListener('popstate', this.hide);
      }
    }
  }
}

Solution:

in hide() function the scope is not the scope of the component.

  openChange(opened: boolean) {
    const self=this;
    function hide(){
      console.log('closing', self.dropdown, self.actions);
      window.removeEventListener('popstate', hide);
      self.dropdown.close();
    }
    if (opened) {
      window.history.pushState('ddOpen',null,null);
      window.addEventListener('popstate',hide);
    } else {
      if(history.state === 'ddOpen'){
        window.history.back();
        window.removeEventListener('popstate', hide);
      }
    }
  }
like image 915
Miklós Dombos Avatar asked May 01 '26 16:05

Miklós Dombos


2 Answers

Try

@ViewChild('dropdownRef', {static:false, read: NgbDropdown}) dropdown: NgbDropdown;
like image 143
Anton Avatar answered May 04 '26 04:05

Anton


Add # before a text for declaring template reference variable

Try like this:

.html

<div #dropdownRef ngbDropdown class="menu" [placement]="placement" (openChange)="openChange($event)">

.ts

 @ViewChild('dropdownRef',{static:false}) dropdown: NgbDropdown;
like image 25
Adrita Sharma Avatar answered May 04 '26 04:05

Adrita Sharma