Skip to content

Commit

Permalink
feat(popover): add isOpen() and shown/hidden events
Browse files Browse the repository at this point in the history
Closes #841
  • Loading branch information
colinmorelli authored and pkozlowski-opensource committed Oct 4, 2016
1 parent 7b82b93 commit 3bbf512
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 3 deletions.
70 changes: 70 additions & 0 deletions src/popover/popover.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,72 @@ describe('ngb-popover', () => {
});
});

describe('visibility', () => {
it('should emit events when showing and hiding popover', () => {
const fixture = createTestComponent(`<div ngbPopover="Great tip!" triggers="click" (shown)="shown()" (hidden)="hidden()"></div>`);
const directive = fixture.debugElement.query(By.directive(NgbPopover));

let shownSpy = spyOn(fixture.componentInstance, 'shown');
let hiddenSpy = spyOn(fixture.componentInstance, 'hidden');

directive.triggerEventHandler('click', {});
fixture.detectChanges();
expect(getWindow(fixture)).not.toBeNull();
expect(shownSpy).toHaveBeenCalled();

directive.triggerEventHandler('click', {});
fixture.detectChanges();
expect(getWindow(fixture)).toBeNull();
expect(hiddenSpy).toHaveBeenCalled();
});

it('should not emit close event when already closed', () => {
const fixture = createTestComponent(`<div ngbPopover="Great tip!" triggers="manual" (shown)="shown()" (hidden)="hidden()"></div>`);

let shownSpy = spyOn(fixture.componentInstance, 'shown');
let hiddenSpy = spyOn(fixture.componentInstance, 'hidden');

fixture.componentInstance.popover.open();
fixture.detectChanges();

fixture.componentInstance.popover.open();
fixture.detectChanges();

expect(getWindow(fixture)).not.toBeNull();
expect(shownSpy).toHaveBeenCalled();
expect(shownSpy.calls.count()).toEqual(1);
expect(hiddenSpy).not.toHaveBeenCalled();
});

it('should not emit open event when already opened', () => {
const fixture = createTestComponent(`<div ngbPopover="Great tip!" triggers="manual" (shown)="shown()" (hidden)="hidden()"></div>`);

let shownSpy = spyOn(fixture.componentInstance, 'shown');
let hiddenSpy = spyOn(fixture.componentInstance, 'hidden');

fixture.componentInstance.popover.close();
fixture.detectChanges();
expect(getWindow(fixture)).toBeNull();
expect(shownSpy).not.toHaveBeenCalled();
expect(hiddenSpy).not.toHaveBeenCalled();
});

it('should report correct visibility', () => {
const fixture = createTestComponent(`<div ngbPopover="Great tip!" triggers="manual"></div>`);
fixture.detectChanges();

expect(fixture.componentInstance.popover.isOpen()).toBeFalsy();

fixture.componentInstance.popover.open();
fixture.detectChanges();
expect(fixture.componentInstance.popover.isOpen()).toBeTruthy();

fixture.componentInstance.popover.close();
fixture.detectChanges();
expect(fixture.componentInstance.popover.isOpen()).toBeFalsy();
});
});

describe('triggers', () => {
beforeEach(() => {
TestBed.configureTestingModule({declarations: [TestComponent], imports: [NgbPopoverModule.forRoot()]});
Expand Down Expand Up @@ -354,6 +420,10 @@ export class TestComponent {
placement: string;

@ViewChild(NgbPopover) popover: NgbPopover;

shown() { }
hidden() { }

}

@Component({selector: 'test-onpush-cmpt', changeDetection: ChangeDetectionStrategy.OnPush, template: ``})
Expand Down
26 changes: 23 additions & 3 deletions src/popover/popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
Component,
Directive,
Input,
Output,
EventEmitter,
ChangeDetectionStrategy,
OnInit,
OnDestroy,
Expand Down Expand Up @@ -55,6 +57,14 @@ export class NgbPopover implements OnInit, OnDestroy {
* Specifies events that should trigger. Supports a space separated list of event names.
*/
@Input() triggers: string;
/**
* Emits an event when the popover is shown
*/
@Output() shown = new EventEmitter();
/**
* Emits an event when the popover is hidden
*/
@Output() hidden = new EventEmitter();

private _popupService: PopupService<NgbPopoverWindow>;
private _windowRef: ComponentRef<NgbPopoverWindow>;
Expand All @@ -77,7 +87,6 @@ export class NgbPopover implements OnInit, OnDestroy {
});
}


/**
* Opens an element’s popover. This is considered a “manual” triggering of the popover.
*/
Expand All @@ -89,15 +98,19 @@ export class NgbPopover implements OnInit, OnDestroy {
// we need to manually invoke change detection since events registered via
// Renderer::listen() are not picked up by change detection with the OnPush strategy
this._windowRef.changeDetectorRef.markForCheck();
this.shown.emit();
}
}

/**
* Closes an element’s popover. This is considered a “manual” triggering of the popover.
*/
close(): void {
this._popupService.close();
this._windowRef = null;
if (this._windowRef) {
this._popupService.close();
this._windowRef = null;
this.hidden.emit();
}
}

/**
Expand All @@ -111,6 +124,13 @@ export class NgbPopover implements OnInit, OnDestroy {
}
}

/**
* Returns whether or not the popover is currently being shown
*/
isOpen(): boolean {
return this._windowRef != null;
}

ngOnInit() {
this._unregisterListenersFn = listenToTriggers(
this._renderer, this._elementRef.nativeElement, this.triggers, this.open.bind(this), this.close.bind(this),
Expand Down

0 comments on commit 3bbf512

Please sign in to comment.