Skip to content

Commit

Permalink
perf(dropdown): register listeners only when the dropdown is opened
Browse files Browse the repository at this point in the history
  • Loading branch information
Thibaut Roy committed Feb 15, 2017
1 parent dc5554b commit 2dd0d76
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
10 changes: 8 additions & 2 deletions src/dropdown/dropdown.spec.ts
@@ -1,7 +1,7 @@
import {TestBed, ComponentFixture, inject} from '@angular/core/testing';
import {createGenericTestComponent} from '../test/common';

import {Component} from '@angular/core';
import {Component, ViewChild} from '@angular/core';
import {By} from '@angular/platform-browser';

import {NgbDropdownModule} from './dropdown.module';
Expand All @@ -21,8 +21,12 @@ describe('ngb-dropdown', () => {
});

it('should initialize inputs with provided config', () => {
const html = '<div ngbDropdown></div>'

const fixture = createTestComponent(html);
const dropdown = fixture.componentInstance.dropdown;
const defaultConfig = new NgbDropdownConfig();
const dropdown = new NgbDropdown(defaultConfig);

expect(dropdown.up).toBe(defaultConfig.up);
expect(dropdown.autoClose).toBe(defaultConfig.autoClose);
});
Expand Down Expand Up @@ -437,6 +441,8 @@ class TestComponent {
isOpen = false;
stateChanges = [];

@ViewChild(NgbDropdown) dropdown: NgbDropdown;

recordStateChange($event) {
this.stateChanges.push($event);
this.isOpen = $event;
Expand Down
39 changes: 35 additions & 4 deletions src/dropdown/dropdown.ts
@@ -1,4 +1,14 @@
import {Directive, Input, Output, EventEmitter, ElementRef} from '@angular/core';
import {
Directive,
Input,
Output,
EventEmitter,
ElementRef,
OnChanges,
OnInit,
OnDestroy,
Renderer
} from '@angular/core';
import {NgbDropdownConfig} from './dropdown-config';

/**
Expand All @@ -12,12 +22,17 @@ import {NgbDropdownConfig} from './dropdown-config';
'[class.dropup]': 'up',
'[class.show]': 'isOpen()',
'(keyup.esc)': 'closeFromOutsideEsc()',
'(document:click)': 'closeFromOutsideClick($event)'
}
})
export class NgbDropdown {
export class NgbDropdown implements OnInit,
OnDestroy {
private _toggleElement: any;

/**
* Holds the remove listener method returned by listenGlobal
*/
private _outsideClickListener;

/**
* Indicates that the dropdown should open upwards
*/
Expand All @@ -39,11 +54,18 @@ export class NgbDropdown {
*/
@Output() openChange = new EventEmitter();

constructor(config: NgbDropdownConfig) {
constructor(config: NgbDropdownConfig, private _renderer: Renderer) {
this.up = config.up;
this.autoClose = config.autoClose;
}

ngOnInit() {
if (this._open) {
this._registerListener();
}
}

ngOnDestroy() { this.close(); }

/**
* Checks if the dropdown menu is open or not.
Expand All @@ -56,6 +78,7 @@ export class NgbDropdown {
open(): void {
if (!this._open) {
this._open = true;
this._registerListener();
this.openChange.emit(true);
}
}
Expand All @@ -66,6 +89,10 @@ export class NgbDropdown {
close(): void {
if (this._open) {
this._open = false;

// Removes "listenGlobal" listener
this._outsideClickListener();

this.openChange.emit(false);
}
}
Expand Down Expand Up @@ -99,6 +126,10 @@ export class NgbDropdown {
set toggleElement(toggleElement: any) { this._toggleElement = toggleElement; }

private _isEventFromToggle($event) { return !!this._toggleElement && this._toggleElement.contains($event.target); }

private _registerListener() {
this._outsideClickListener = this._renderer.listenGlobal('document', 'click', (e) => this.closeFromOutsideClick(e));
}
}

/**
Expand Down

0 comments on commit 2dd0d76

Please sign in to comment.