diff --git a/src/lib/menu/index.ts b/src/lib/menu/index.ts index e2a8fae18c6d..1545666e8449 100644 --- a/src/lib/menu/index.ts +++ b/src/lib/menu/index.ts @@ -9,7 +9,7 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {OverlayModule, MdCommonModule} from '../core'; -import {MdMenu} from './menu-directive'; +import {MdMenu, MD_MENU_DEFAULT_OPTIONS} from './menu-directive'; import {MdMenuItem} from './menu-item'; import {MdMenuTrigger, MD_MENU_SCROLL_STRATEGY_PROVIDER} from './menu-trigger'; import {MdRippleModule} from '../core/ripple/index'; @@ -24,7 +24,17 @@ import {MdRippleModule} from '../core/ripple/index'; ], exports: [MdMenu, MdMenuItem, MdMenuTrigger, MdCommonModule], declarations: [MdMenu, MdMenuItem, MdMenuTrigger], - providers: [MD_MENU_SCROLL_STRATEGY_PROVIDER], + providers: [ + MD_MENU_SCROLL_STRATEGY_PROVIDER, + { + provide: MD_MENU_DEFAULT_OPTIONS, + useValue: { + overlapTrigger: true, + xPosition: 'after', + yPosition: 'below', + }, + } + ], }) export class MdMenuModule {} diff --git a/src/lib/menu/menu-directive.ts b/src/lib/menu/menu-directive.ts index cd9c102da34f..425e66547ec1 100644 --- a/src/lib/menu/menu-directive.ts +++ b/src/lib/menu/menu-directive.ts @@ -20,6 +20,8 @@ import { ViewEncapsulation, ElementRef, ChangeDetectionStrategy, + InjectionToken, + Inject, } from '@angular/core'; import {AnimationEvent} from '@angular/animations'; import {MenuPositionX, MenuPositionY} from './menu-positions'; @@ -34,6 +36,16 @@ import {merge} from 'rxjs/observable/merge'; import {Observable} from 'rxjs/Observable'; import {Direction} from '../core'; +/** Default `md-menu` options that can be overridden. */ +export interface MdMenuDefaultOptions { + xPosition: MenuPositionX; + yPosition: MenuPositionY; + overlapTrigger: boolean; +} + +/** Injection token to be used to override the default options for `md-menu`. */ +export const MD_MENU_DEFAULT_OPTIONS = + new InjectionToken('md-menu-default-options'); @Component({ moduleId: module.id, @@ -50,8 +62,8 @@ import {Direction} from '../core'; }) export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy { private _keyManager: FocusKeyManager; - private _xPosition: MenuPositionX = 'after'; - private _yPosition: MenuPositionY = 'below'; + private _xPosition: MenuPositionX = this._defaultOptions.xPosition; + private _yPosition: MenuPositionY = this._defaultOptions.yPosition; /** Subscription to tab events on the menu panel */ private _tabSubscription: Subscription; @@ -96,7 +108,7 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy { @ContentChildren(MdMenuItem) items: QueryList; /** Whether the menu should overlap its trigger. */ - @Input() overlapTrigger = true; + @Input() overlapTrigger = this._defaultOptions.overlapTrigger; /** * This method takes classes set on the host md-menu element and applies them on the @@ -120,7 +132,9 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy { /** Event emitted when the menu is closed. */ @Output() close = new EventEmitter(); - constructor(private _elementRef: ElementRef) { } + constructor( + private _elementRef: ElementRef, + @Inject(MD_MENU_DEFAULT_OPTIONS) private _defaultOptions: MdMenuDefaultOptions) { } ngAfterContentInit() { this._keyManager = new FocusKeyManager(this.items).withWrap(); diff --git a/src/lib/menu/menu.spec.ts b/src/lib/menu/menu.spec.ts index 4e6f0a1882b6..22914dae3630 100644 --- a/src/lib/menu/menu.spec.ts +++ b/src/lib/menu/menu.spec.ts @@ -25,6 +25,7 @@ import { MenuPositionX, MenuPositionY, MdMenu, + MD_MENU_DEFAULT_OPTIONS, } from './index'; import {MENU_PANEL_TOP_PADDING} from './menu-trigger'; import {extendObject} from '../core/util/object-extend'; @@ -875,6 +876,29 @@ describe('MdMenu', () => { }); +describe('MdMenu default overrides', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [MdMenuModule, NoopAnimationsModule], + declarations: [SimpleMenu], + providers: [{ + provide: MD_MENU_DEFAULT_OPTIONS, + useValue: {overlapTrigger: false, xPosition: 'before', yPosition: 'above'}, + }], + }).compileComponents(); + })); + + it('should allow for the default menu options to be overridden', () => { + const fixture = TestBed.createComponent(SimpleMenu); + fixture.detectChanges(); + const menu = fixture.componentInstance.menu; + + expect(menu.overlapTrigger).toBe(false); + expect(menu.xPosition).toBe('before'); + expect(menu.yPosition).toBe('above'); + }); +}); + @Component({ template: ` diff --git a/src/lib/menu/menu.ts b/src/lib/menu/menu.ts index ac3ee4140b25..1eff665c413b 100644 --- a/src/lib/menu/menu.ts +++ b/src/lib/menu/menu.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -export {MdMenu} from './menu-directive'; +export {MdMenu, MdMenuDefaultOptions, MD_MENU_DEFAULT_OPTIONS} from './menu-directive'; export {MdMenuItem} from './menu-item'; export {MdMenuTrigger} from './menu-trigger'; export {MdMenuPanel} from './menu-panel';