Skip to content

Commit

Permalink
feat(menu): expose close method on element scope
Browse files Browse the repository at this point in the history
Exposes the $mdCloseMenu method on the menu's scope, allowing for custom closing behavior.

Fixes angular#8446.
  • Loading branch information
crisbeto committed Aug 1, 2016
1 parent aaf682a commit 3c72444
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 21 deletions.
3 changes: 3 additions & 0 deletions src/components/menu/js/menuController.js
Expand Up @@ -195,6 +195,9 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r
}
};

// Expose the close method on the scope, allowing for use in the template.
$scope.$mdCloseMenu = this.close;

/**
* Build a nice object out of our string attribute which specifies the
* target mode for left and top positioning
Expand Down
23 changes: 13 additions & 10 deletions src/components/menu/js/menuDirective.js
Expand Up @@ -12,7 +12,8 @@
* left in the DOM and is used to open the menu. This element is called the trigger element.
* The trigger element's scope has access to `$mdOpenMenu($event)`
* which it may call to open the menu. By passing $event as argument, the
* corresponding event is stopped from propagating up the DOM-tree.
* corresponding event is stopped from propagating up the DOM-tree. Similarly, `$mdCloseMenu()`
* can be used to close the menu.
*
* The second element is the `md-menu-content` element which represents the
* contents of the menu when it is open. Typically this will contain `md-menu-item`s,
Expand Down Expand Up @@ -105,7 +106,7 @@
*
* ### Auto Focus
* By default, when a menu opens, `md-menu` focuses the first button in the menu content.
*
*
* But sometimes you would like to focus another specific menu item instead of the first.<br/>
* This can be done by applying the `md-autofocus` directive on the given element.
*
Expand All @@ -123,16 +124,18 @@
* Sometimes you would like to be able to click on a menu item without having the menu
* close. To do this, ngMaterial exposes the `md-prevent-menu-close` attribute which
* can be added to a button inside a menu to stop the menu from automatically closing.
* You can then close the menu programatically by injecting `$mdMenu` and calling
* `$mdMenu.hide()`.
* You can then close the menu either by using `$mdCloseMenu()` in the template,
* or programmatically by injecting `$mdMenu` and calling `$mdMenu.hide()`.
*
* <hljs lang="html">
* <md-menu-item>
* <md-button ng-click="doSomething()" aria-label="Do something" md-prevent-menu-close="md-prevent-menu-close">
* <md-icon md-menu-align-target md-svg-icon="call:phone"></md-icon>
* Do Something
* </md-button>
* </md-menu-item>
* <md-menu-content ng-mouseleave="$mdCloseMenu()">
* <md-menu-item>
* <md-button ng-click="doSomething()" aria-label="Do something" md-prevent-menu-close="md-prevent-menu-close">
* <md-icon md-menu-align-target md-svg-icon="call:phone"></md-icon>
* Do Something
* </md-button>
* </md-menu-item>
* </md-menu-content>
* </hljs>
*
* @usage
Expand Down
31 changes: 20 additions & 11 deletions src/components/menu/menu.spec.js
Expand Up @@ -66,25 +66,23 @@ describe('material.components.menu', function() {
});

it('opens on click without $event', function() {
var noEvent = true;
var menu = setup('ng-click', noEvent);
var menu = setup('ng-click="$mdOpenMenu()"');
openMenu(menu);
expect(getOpenMenuContainer(menu).length).toBe(1);
closeMenu(menu);
expect(getOpenMenuContainer(menu).length).toBe(0);
});

it('opens on mouseEnter', function() {
var menu = setup('ng-mouseenter');
var menu = setup('ng-mouseenter="$mdOpenMenu($event)"');
openMenu(menu, 'mouseenter');
expect(getOpenMenuContainer(menu).length).toBe(1);
closeMenu(menu);
expect(getOpenMenuContainer(menu).length).toBe(0);
});

it('opens on mouseEnter without $event', function() {
var noEvent = true;
var menu = setup('ng-mouseenter', noEvent);
var menu = setup('ng-mouseenter="$mdOpenMenu()"');
openMenu(menu, 'mouseenter');
expect(getOpenMenuContainer(menu).length).toBe(1);
closeMenu(menu);
Expand Down Expand Up @@ -116,7 +114,7 @@ describe('material.components.menu', function() {

it('should remove the backdrop if the container scope got destroyed', inject(function($document, $rootScope) {
var scope = $rootScope.$new();
var menu = setup(null, null, scope);
var menu = setup(null, scope);

openMenu(menu);
expect($document.find('md-backdrop').length).not.toBe(0);
Expand Down Expand Up @@ -214,6 +212,18 @@ describe('material.components.menu', function() {
expect(getOpenMenuContainer(menu).length).toBe(0);
});

it('closes via the scope method', function() {
var menu = setup('ng-mouseenter="$mdOpenMenu($event)" ng-mouseleave="$mdCloseMenu()"');

expect(getOpenMenuContainer(menu).length).toBe(0);
openMenu(menu, 'mouseenter');
expect(getOpenMenuContainer(menu).length).toBe(1);

menu.find('button').triggerHandler('mouseleave');
waitForMenuClose();
expect(getOpenMenuContainer(menu).length).toBe(0);
});

itClosesWithAttributes([
'data-ng-click', 'x-ng-click',
'ui-sref', 'data-ui-sref', 'x-ui-sref',
Expand All @@ -226,7 +236,7 @@ describe('material.components.menu', function() {
}

function testAttribute(attr) {
return inject(function($rootScope, $compile, $timeout, $browser) {
return inject(function($rootScope, $compile, $timeout) {
var template = '' +
'<md-menu>' +
' <button ng-click="$mdOpenMenu($event)">Hello World</button>' +
Expand Down Expand Up @@ -255,17 +265,17 @@ describe('material.components.menu', function() {
}
});

function setup(triggerType, noEvent, scope) {
function setup(buttonAttrs, scope) {
var menu,
template = $mdUtil.supplant('' +
'<md-menu>' +
' <button {0}="$mdOpenMenu({1})">Hello World</button>' +
' <button {0}>Hello World</button>' +
' <md-menu-content>' +
' <md-menu-item>' +
' <md-button ng-click="doSomething($event)"></md-button>' +
' </md-menu-item>' +
' </md-menu-content>' +
'</md-menu>',[ triggerType || 'ng-click', noEvent ? '' : "$event" ]);
'</md-menu>', [ buttonAttrs || 'ng-click="$mdOpenMenu($event)"' ]);

inject(function($compile, $rootScope) {
$rootScope.doSomething = function($event) {
Expand Down Expand Up @@ -305,7 +315,6 @@ describe('material.components.menu', function() {

function closeMenu() {
inject(function($document) {
$document.find('md-backdrop');
$document.find('md-backdrop').triggerHandler('click');
waitForMenuClose();
});
Expand Down

0 comments on commit 3c72444

Please sign in to comment.