Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 213ca7e

Browse files
committed
feat(menu): expose close method on element scope
Exposes the $mdCloseMenu method on the menu's scope, allowing for custom closing behavior. Fixes #8446.
1 parent 0592dfa commit 213ca7e

File tree

3 files changed

+35
-20
lines changed

3 files changed

+35
-20
lines changed

src/components/menu/js/menuController.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r
195195
}
196196
};
197197

198+
// Expose the close method on the scope, allowing for use in the template.
199+
$scope.$mdCloseMenu = this.close;
200+
198201
/**
199202
* Build a nice object out of our string attribute which specifies the
200203
* target mode for left and top positioning

src/components/menu/js/menuDirective.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
* left in the DOM and is used to open the menu. This element is called the trigger element.
1313
* The trigger element's scope has access to `$mdOpenMenu($event)`
1414
* which it may call to open the menu. By passing $event as argument, the
15-
* corresponding event is stopped from propagating up the DOM-tree.
15+
* corresponding event is stopped from propagating up the DOM-tree. Similarly, `$mdCloseMenu()`
16+
* can be used to close the menu.
1617
*
1718
* The second element is the `md-menu-content` element which represents the
1819
* contents of the menu when it is open. Typically this will contain `md-menu-item`s,
@@ -123,16 +124,18 @@
123124
* Sometimes you would like to be able to click on a menu item without having the menu
124125
* close. To do this, ngMaterial exposes the `md-prevent-menu-close` attribute which
125126
* can be added to a button inside a menu to stop the menu from automatically closing.
126-
* You can then close the menu programatically by injecting `$mdMenu` and calling
127-
* `$mdMenu.hide()`.
127+
* You can then close the menu either by using `$mdCloseMenu()` in the template,
128+
* or programatically by injecting `$mdMenu` and calling `$mdMenu.hide()`.
128129
*
129130
* <hljs lang="html">
130-
* <md-menu-item>
131-
* <md-button ng-click="doSomething()" aria-label="Do something" md-prevent-menu-close="md-prevent-menu-close">
132-
* <md-icon md-menu-align-target md-svg-icon="call:phone"></md-icon>
133-
* Do Something
134-
* </md-button>
135-
* </md-menu-item>
131+
* <md-menu-content ng-mouseleave="$mdCloseMenu()">
132+
* <md-menu-item>
133+
* <md-button ng-click="doSomething()" aria-label="Do something" md-prevent-menu-close="md-prevent-menu-close">
134+
* <md-icon md-menu-align-target md-svg-icon="call:phone"></md-icon>
135+
* Do Something
136+
* </md-button>
137+
* </md-menu-item>
138+
* </md-menu-content>
136139
* </hljs>
137140
*
138141
* @usage

src/components/menu/menu.spec.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,23 @@ describe('material.components.menu', function() {
6666
});
6767

6868
it('opens on click without $event', function() {
69-
var noEvent = true;
70-
var menu = setup('ng-click', noEvent);
69+
var menu = setup('ng-click="$mdOpenMenu()"');
7170
openMenu(menu);
7271
expect(getOpenMenuContainer(menu).length).toBe(1);
7372
closeMenu(menu);
7473
expect(getOpenMenuContainer(menu).length).toBe(0);
7574
});
7675

7776
it('opens on mouseEnter', function() {
78-
var menu = setup('ng-mouseenter');
77+
var menu = setup('ng-mouseenter="$mdOpenMenu($event)"');
7978
openMenu(menu, 'mouseenter');
8079
expect(getOpenMenuContainer(menu).length).toBe(1);
8180
closeMenu(menu);
8281
expect(getOpenMenuContainer(menu).length).toBe(0);
8382
});
8483

8584
it('opens on mouseEnter without $event', function() {
86-
var noEvent = true;
87-
var menu = setup('ng-mouseenter', noEvent);
85+
var menu = setup('ng-mouseenter="$mdOpenMenu()"');
8886
openMenu(menu, 'mouseenter');
8987
expect(getOpenMenuContainer(menu).length).toBe(1);
9088
closeMenu(menu);
@@ -116,7 +114,7 @@ describe('material.components.menu', function() {
116114

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

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

215+
it('closes via the scope method', function() {
216+
var menu = setup('ng-mouseenter="$mdOpenMenu($event)" ng-mouseleave="$mdCloseMenu()"');
217+
218+
expect(getOpenMenuContainer(menu).length).toBe(0);
219+
openMenu(menu, 'mouseenter');
220+
expect(getOpenMenuContainer(menu).length).toBe(1);
221+
222+
menu.find('button').triggerHandler('mouseleave');
223+
waitForMenuClose();
224+
expect(getOpenMenuContainer(menu).length).toBe(0);
225+
});
226+
217227
itClosesWithAttributes([
218228
'data-ng-click', 'x-ng-click',
219229
'ui-sref', 'data-ui-sref', 'x-ui-sref',
@@ -226,7 +236,7 @@ describe('material.components.menu', function() {
226236
}
227237

228238
function testAttribute(attr) {
229-
return inject(function($rootScope, $compile, $timeout, $browser) {
239+
return inject(function($rootScope, $compile, $timeout) {
230240
var template = '' +
231241
'<md-menu>' +
232242
' <button ng-click="$mdOpenMenu($event)">Hello World</button>' +
@@ -255,17 +265,17 @@ describe('material.components.menu', function() {
255265
}
256266
});
257267

258-
function setup(triggerType, noEvent, scope) {
268+
function setup(buttonAttrs, scope) {
259269
var menu,
260270
template = $mdUtil.supplant('' +
261271
'<md-menu>' +
262-
' <button {0}="$mdOpenMenu({1})">Hello World</button>' +
272+
' <button {0}>Hello World</button>' +
263273
' <md-menu-content>' +
264274
' <md-menu-item>' +
265275
' <md-button ng-click="doSomething($event)"></md-button>' +
266276
' </md-menu-item>' +
267277
' </md-menu-content>' +
268-
'</md-menu>',[ triggerType || 'ng-click', noEvent ? '' : "$event" ]);
278+
'</md-menu>', [ buttonAttrs || 'ng-click="$mdOpenMenu($event)"' ]);
269279

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

306316
function closeMenu() {
307317
inject(function($document) {
308-
$document.find('md-backdrop');
309318
$document.find('md-backdrop').triggerHandler('click');
310319
waitForMenuClose();
311320
});

0 commit comments

Comments
 (0)