diff --git a/src/lib/core/a11y/list-key-manager.ts b/src/lib/core/a11y/list-key-manager.ts index 4458ca9a80e..3dd1bfd6a03 100644 --- a/src/lib/core/a11y/list-key-manager.ts +++ b/src/lib/core/a11y/list-key-manager.ts @@ -1,5 +1,7 @@ -import {EventEmitter, Output, QueryList} from '@angular/core'; +import {QueryList} from '@angular/core'; import {UP_ARROW, DOWN_ARROW, TAB} from '../core'; +import {Observable} from 'rxjs/Observable'; +import {Subject} from 'rxjs/Subject'; /** * This is the interface for focusable items (used by the ListKeyManager). @@ -16,15 +18,18 @@ export interface MdFocusable { */ export class ListKeyManager { private _focusedItemIndex: number; - - /** - * This event is emitted any time the TAB key is pressed, so components can react - * when focus is shifted off of the list. - */ - @Output() tabOut = new EventEmitter(); + private _tabOut: Subject = new Subject(); constructor(private _items: QueryList) {} + /** + * Observable that emits any time the TAB key is pressed, so components can react + * when focus is shifted off of the list. + */ + get tabOut(): Observable { + return this._tabOut.asObservable(); + } + set focusedItemIndex(value: number) { this._focusedItemIndex = value; } @@ -35,7 +40,7 @@ export class ListKeyManager { } else if (event.keyCode === UP_ARROW) { this._focusPreviousItem(); } else if (event.keyCode === TAB) { - this.tabOut.emit(); + this._tabOut.next(null); } } diff --git a/src/lib/menu/menu-directive.ts b/src/lib/menu/menu-directive.ts index 600e793bc3d..b91d92728b0 100644 --- a/src/lib/menu/menu-directive.ts +++ b/src/lib/menu/menu-directive.ts @@ -1,11 +1,13 @@ // TODO(kara): prevent-close functionality import { + AfterContentInit, Attribute, Component, ContentChildren, EventEmitter, Input, + OnDestroy, Output, QueryList, TemplateRef, @@ -17,6 +19,7 @@ import {MdMenuInvalidPositionX, MdMenuInvalidPositionY} from './menu-errors'; import {MdMenuItem} from './menu-item'; import {ListKeyManager} from '../core/a11y/list-key-manager'; import {MdMenuPanel} from './menu-panel'; +import {Subscription} from 'rxjs/Subscription'; @Component({ moduleId: module.id, @@ -27,10 +30,13 @@ import {MdMenuPanel} from './menu-panel'; encapsulation: ViewEncapsulation.None, exportAs: 'mdMenu' }) -export class MdMenu implements MdMenuPanel { +export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy { private _keyManager: ListKeyManager; - // config object to be passed into the menu's ngClass + /** Subscription to tab events on the menu panel */ + private _tabSubscription: Subscription; + + /** Config object to be passed into the menu's ngClass */ _classList: Object; positionX: MenuPositionX = 'after'; @@ -45,11 +51,20 @@ export class MdMenu implements MdMenuPanel { if (posY) { this._setPositionY(posY); } } + // TODO: internal ngAfterContentInit() { this._keyManager = new ListKeyManager(this.items); - this._keyManager.tabOut.subscribe(() => this._emitCloseEvent()); + this._tabSubscription = this._keyManager.tabOut.subscribe(() => { + this._emitCloseEvent(); + }); } + // TODO: internal + ngOnDestroy() { + this._tabSubscription.unsubscribe(); + } + + /** * This method takes classes set on the host md-menu element and applies them on the * menu template that displays in the overlay container. Otherwise, it's difficult