Skip to content

Commit 771afd9

Browse files
authored
fix(material-experimental/mdc-menu): ensure mat-mdc- prefix on all classes (#23559)
* fix(material-experimental/mdc-menu): ensure mat-mdc- prefix on all classes The MDC menu trigger had `.mat-menu-trigger` class because it was using the same directive as the non-MDC menu. This PR refactors the trigger and content directives to extend a common base class. * fixup! fix(material-experimental/mdc-menu): ensure mat-mdc- prefix on all classes * fixup! fix(material-experimental/mdc-menu): ensure mat-mdc- prefix on all classes * fixup! fix(material-experimental/mdc-menu): ensure mat-mdc- prefix on all classes
1 parent 04d2aaa commit 771afd9

File tree

9 files changed

+128
-72
lines changed

9 files changed

+128
-72
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Directive} from '@angular/core';
10+
import {_MatMenuContentBase, _MatMenuTriggerBase, MAT_MENU_CONTENT} from '@angular/material/menu';
11+
12+
/** Directive applied to an element that should trigger a `mat-menu`. */
13+
@Directive({
14+
selector: `[mat-menu-trigger-for], [matMenuTriggerFor]`,
15+
host: {
16+
'class': 'mat-mdc-menu-trigger',
17+
},
18+
exportAs: 'matMenuTrigger'
19+
})
20+
export class MatMenuTrigger extends _MatMenuTriggerBase {}
21+
22+
/** Menu content that will be rendered lazily once the menu is opened. */
23+
@Directive({
24+
selector: 'ng-template[matMenuContent]',
25+
providers: [{provide: MAT_MENU_CONTENT, useExisting: MatMenuContent}],
26+
})
27+
export class MatMenuContent extends _MatMenuContentBase {}

src/material-experimental/mdc-menu/module.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,27 @@ import {CommonModule} from '@angular/common';
1010
import {NgModule} from '@angular/core';
1111
import {MatCommonModule, MatRippleModule} from '@angular/material-experimental/mdc-core';
1212
import {OverlayModule} from '@angular/cdk/overlay';
13-
import {_MatMenuDirectivesModule} from '@angular/material/menu';
1413
import {CdkScrollableModule} from '@angular/cdk/scrolling';
15-
import {MatMenu, MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER} from './menu';
14+
import {MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER, MatMenu} from './menu';
1615
import {MatMenuItem} from './menu-item';
16+
import {MatMenuContent, MatMenuTrigger} from './directives';
1717

1818
@NgModule({
1919
imports: [
2020
CommonModule,
2121
MatRippleModule,
2222
MatCommonModule,
2323
OverlayModule,
24-
_MatMenuDirectivesModule
2524
],
26-
exports: [CdkScrollableModule, MatMenu, MatCommonModule, MatMenuItem, _MatMenuDirectivesModule],
27-
declarations: [MatMenu, MatMenuItem],
25+
exports: [
26+
CdkScrollableModule,
27+
MatMenu,
28+
MatCommonModule,
29+
MatMenuItem,
30+
MatMenuContent,
31+
MatMenuTrigger
32+
],
33+
declarations: [MatMenu, MatMenuItem, MatMenuContent, MatMenuTrigger],
2834
providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER]
2935
})
3036
export class MatMenuModule {}

src/material-experimental/mdc-menu/public-api.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,17 @@
88

99
export {MatMenu} from './menu';
1010
export {MatMenuItem} from './menu-item';
11+
export {MatMenuTrigger, MatMenuContent} from './directives';
1112
export * from './module';
1213

1314
export {
14-
_MatMenuDirectivesModule,
1515
fadeInItems,
1616
MAT_MENU_DEFAULT_OPTIONS,
1717
MAT_MENU_PANEL,
1818
MAT_MENU_SCROLL_STRATEGY,
1919
matMenuAnimations,
20-
MatMenuContent,
2120
MatMenuDefaultOptions,
2221
MatMenuPanel,
23-
MatMenuTrigger,
2422
MenuPositionX,
2523
MenuPositionY,
2624
transformMenu,

src/material-experimental/mdc-menu/testing/menu-harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
export class MatMenuHarness extends _MatMenuHarnessBase<
1919
typeof MatMenuItemHarness, MatMenuItemHarness, MenuItemHarnessFilters> {
2020
/** The selector for the host element of a `MatMenu` instance. */
21-
static hostSelector = '.mat-menu-trigger';
21+
static hostSelector = '.mat-mdc-menu-trigger';
2222
protected _itemClass = MatMenuItemHarness;
2323

2424
/**

src/material/menu/menu-content.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,8 @@ import {Subject} from 'rxjs';
2929
*/
3030
export const MAT_MENU_CONTENT = new InjectionToken<MatMenuContent>('MatMenuContent');
3131

32-
/**
33-
* Menu content that will be rendered lazily once the menu is opened.
34-
*/
35-
@Directive({
36-
selector: 'ng-template[matMenuContent]',
37-
providers: [{provide: MAT_MENU_CONTENT, useExisting: MatMenuContent}],
38-
})
39-
export class MatMenuContent implements OnDestroy {
32+
@Directive()
33+
export abstract class _MatMenuContentBase implements OnDestroy {
4034
private _portal: TemplatePortal<any>;
4135
private _outlet: DomPortalOutlet;
4236

@@ -105,3 +99,12 @@ export class MatMenuContent implements OnDestroy {
10599
}
106100
}
107101
}
102+
103+
/**
104+
* Menu content that will be rendered lazily once the menu is opened.
105+
*/
106+
@Directive({
107+
selector: 'ng-template[matMenuContent]',
108+
providers: [{provide: MAT_MENU_CONTENT, useExisting: MatMenuContent}],
109+
})
110+
export class MatMenuContent extends _MatMenuContentBase {}

src/material/menu/menu-module.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,22 @@ import {MatMenuContent} from './menu-content';
1616
import {MatMenuItem} from './menu-item';
1717
import {MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER, MatMenuTrigger} from './menu-trigger';
1818

19-
/**
20-
* Used by both the current `MatMenuModule` and the MDC `MatMenuModule`
21-
* to declare the menu-related directives.
22-
*/
23-
@NgModule({
24-
exports: [MatMenuTrigger, MatMenuContent, MatCommonModule],
25-
declarations: [
26-
MatMenuTrigger,
27-
MatMenuContent,
28-
],
29-
providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER]
30-
})
31-
export class _MatMenuDirectivesModule {}
32-
3319
@NgModule({
3420
imports: [
3521
CommonModule,
3622
MatCommonModule,
3723
MatRippleModule,
3824
OverlayModule,
39-
_MatMenuDirectivesModule,
4025
],
41-
exports: [CdkScrollableModule, MatCommonModule, MatMenu, MatMenuItem, _MatMenuDirectivesModule],
42-
declarations: [MatMenu, MatMenuItem],
26+
exports: [
27+
CdkScrollableModule,
28+
MatCommonModule,
29+
MatMenu,
30+
MatMenuItem,
31+
MatMenuTrigger,
32+
MatMenuContent
33+
],
34+
declarations: [MatMenu, MatMenuItem, MatMenuTrigger, MatMenuContent],
4335
providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER]
4436
})
4537
export class MatMenuModule {}

src/material/menu/menu-trigger.ts

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ import {
2020
Overlay,
2121
OverlayConfig,
2222
OverlayRef,
23-
VerticalConnectionPos,
2423
ScrollStrategy,
24+
VerticalConnectionPos,
2525
} from '@angular/cdk/overlay';
2626
import {TemplatePortal} from '@angular/cdk/portal';
2727
import {
2828
AfterContentInit,
2929
Directive,
3030
ElementRef,
3131
EventEmitter,
32+
HostBinding,
33+
HostListener,
3234
Inject,
3335
InjectionToken,
3436
Input,
@@ -41,10 +43,10 @@ import {
4143
import {normalizePassiveListenerOptions} from '@angular/cdk/platform';
4244
import {asapScheduler, merge, Observable, of as observableOf, Subscription} from 'rxjs';
4345
import {delay, filter, take, takeUntil} from 'rxjs/operators';
44-
import {MenuCloseReason, _MatMenuBase} from './menu';
46+
import {_MatMenuBase, MenuCloseReason} from './menu';
4547
import {throwMatMenuMissingError, throwMatMenuRecursiveError} from './menu-errors';
4648
import {MatMenuItem} from './menu-item';
47-
import {MatMenuPanel, MAT_MENU_PANEL} from './menu-panel';
49+
import {MAT_MENU_PANEL, MatMenuPanel} from './menu-panel';
4850
import {MenuPositionX, MenuPositionY} from './menu-positions';
4951

5052
/** Injection token that determines the scroll handling while the menu is open. */
@@ -71,21 +73,8 @@ const passiveEventListenerOptions = normalizePassiveListenerOptions({passive: tr
7173

7274
// TODO(andrewseguin): Remove the kebab versions in favor of camelCased attribute selectors
7375

74-
/** Directive applied to an element that should trigger a `mat-menu`. */
75-
@Directive({
76-
selector: `[mat-menu-trigger-for], [matMenuTriggerFor]`,
77-
host: {
78-
'class': 'mat-menu-trigger',
79-
'aria-haspopup': 'true',
80-
'[attr.aria-expanded]': 'menuOpen || null',
81-
'[attr.aria-controls]': 'menuOpen ? menu.panelId : null',
82-
'(mousedown)': '_handleMousedown($event)',
83-
'(keydown)': '_handleKeydown($event)',
84-
'(click)': '_handleClick($event)',
85-
},
86-
exportAs: 'matMenuTrigger'
87-
})
88-
export class MatMenuTrigger implements AfterContentInit, OnDestroy {
76+
@Directive()
77+
export abstract class _MatMenuTriggerBase implements AfterContentInit, OnDestroy {
8978
private _portal: TemplatePortal;
9079
private _overlayRef: OverlayRef | null = null;
9180
private _menuOpen: boolean = false;
@@ -114,6 +103,22 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
114103
// the first item of the list when the menu is opened via the keyboard
115104
_openedBy: Exclude<FocusOrigin, 'program' | null> | undefined = undefined;
116105

106+
@HostBinding('attr.aria-expanded')
107+
// Need tp use getter for HostBinding
108+
// tslint:disable-next-line:no-private-getters
109+
get _ariaExpanded() {
110+
return this.menuOpen || null;
111+
}
112+
113+
@HostBinding('attr.aria-controls')
114+
// Need tp use getter for HostBinding
115+
// tslint:disable-next-line:no-private-getters
116+
get _ariaControl() {
117+
return this.menuOpen ? this.menu.panelId : null;
118+
}
119+
120+
@HostBinding('attr.aria-haspopup') _ariaHaspopup = true;
121+
117122
/**
118123
* @deprecated
119124
* @breaking-change 8.0.0
@@ -508,6 +513,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
508513
}
509514

510515
/** Handles mouse presses on the trigger. */
516+
@HostListener('mousedown', ['$event'])
511517
_handleMousedown(event: MouseEvent): void {
512518
if (!isFakeMousedownFromScreenReader(event)) {
513519
// Since right or middle button clicks won't trigger the `click` event,
@@ -524,6 +530,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
524530
}
525531

526532
/** Handles key presses on the trigger. */
533+
@HostListener('keydown', ['$event'])
527534
_handleKeydown(event: KeyboardEvent): void {
528535
const keyCode = event.keyCode;
529536

@@ -541,6 +548,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
541548
}
542549

543550
/** Handles click events on the trigger. */
551+
@HostListener('click', ['$event'])
544552
_handleClick(event: MouseEvent): void {
545553
if (this.triggersSubmenu()) {
546554
// Stop event propagation to avoid closing the parent menu.
@@ -597,3 +605,13 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
597605
}
598606

599607
}
608+
609+
/** Directive applied to an element that should trigger a `mat-menu`. */
610+
@Directive({
611+
selector: `[mat-menu-trigger-for], [matMenuTriggerFor]`,
612+
host: {
613+
'class': 'mat-menu-trigger',
614+
},
615+
exportAs: 'matMenuTrigger'
616+
})
617+
export class MatMenuTrigger extends _MatMenuTriggerBase {}

src/material/menu/public-api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export {
1313
_MatMenuBase,
1414
} from './menu';
1515
export {MatMenuItem} from './menu-item';
16-
export {MatMenuTrigger, MAT_MENU_SCROLL_STRATEGY} from './menu-trigger';
16+
export {MatMenuTrigger, MAT_MENU_SCROLL_STRATEGY, _MatMenuTriggerBase} from './menu-trigger';
1717
export {MatMenuPanel, MAT_MENU_PANEL} from './menu-panel';
1818
export * from './menu-module';
1919
export * from './menu-animations';

tools/public_api_guard/material/menu.md

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import { FocusableOption } from '@angular/cdk/a11y';
2424
import { FocusMonitor } from '@angular/cdk/a11y';
2525
import { FocusOrigin } from '@angular/cdk/a11y';
2626
import * as i0 from '@angular/core';
27-
import * as i3 from '@angular/material/core';
28-
import * as i6 from '@angular/common';
27+
import * as i5 from '@angular/common';
28+
import * as i6 from '@angular/material/core';
2929
import * as i7 from '@angular/cdk/overlay';
3030
import * as i8 from '@angular/cdk/scrolling';
3131
import { InjectionToken } from '@angular/core';
@@ -162,17 +162,25 @@ export class _MatMenuBase implements AfterContentInit, MatMenuPanel<MatMenuItem>
162162
}
163163

164164
// @public
165-
export class MatMenuContent implements OnDestroy {
165+
export class MatMenuContent extends _MatMenuContentBase {
166+
// (undocumented)
167+
static ɵdir: i0.ɵɵDirectiveDeclaration<MatMenuContent, "ng-template[matMenuContent]", never, {}, {}, never>;
168+
// (undocumented)
169+
static ɵfac: i0.ɵɵFactoryDeclaration<MatMenuContent, never>;
170+
}
171+
172+
// @public (undocumented)
173+
export abstract class _MatMenuContentBase implements OnDestroy {
166174
constructor(_template: TemplateRef<any>, _componentFactoryResolver: ComponentFactoryResolver, _appRef: ApplicationRef, _injector: Injector, _viewContainerRef: ViewContainerRef, _document: any, _changeDetectorRef?: ChangeDetectorRef | undefined);
167175
attach(context?: any): void;
168176
readonly _attached: Subject<void>;
169177
detach(): void;
170178
// (undocumented)
171179
ngOnDestroy(): void;
172180
// (undocumented)
173-
static ɵdir: i0.ɵɵDirectiveDeclaration<MatMenuContent, "ng-template[matMenuContent]", never, {}, {}, never>;
181+
static ɵdir: i0.ɵɵDirectiveDeclaration<_MatMenuContentBase, never, never, {}, {}, never>;
174182
// (undocumented)
175-
static ɵfac: i0.ɵɵFactoryDeclaration<MatMenuContent, never>;
183+
static ɵfac: i0.ɵɵFactoryDeclaration<_MatMenuContentBase, never>;
176184
}
177185

178186
// @public
@@ -185,16 +193,6 @@ export interface MatMenuDefaultOptions {
185193
yPosition: MenuPositionY;
186194
}
187195

188-
// @public
189-
export class _MatMenuDirectivesModule {
190-
// (undocumented)
191-
static ɵfac: i0.ɵɵFactoryDeclaration<_MatMenuDirectivesModule, never>;
192-
// (undocumented)
193-
static ɵinj: i0.ɵɵInjectorDeclaration<_MatMenuDirectivesModule>;
194-
// (undocumented)
195-
static ɵmod: i0.ɵɵNgModuleDeclaration<_MatMenuDirectivesModule, [typeof i1.MatMenuTrigger, typeof i2.MatMenuContent], never, [typeof i1.MatMenuTrigger, typeof i2.MatMenuContent, typeof i3.MatCommonModule]>;
196-
}
197-
198196
// @public
199197
export class MatMenuItem extends _MatMenuItemBase implements FocusableOption, CanDisable, CanDisableRipple, AfterViewInit, OnDestroy {
200198
constructor(_elementRef: ElementRef<HTMLElement>,
@@ -236,7 +234,7 @@ export class MatMenuModule {
236234
// (undocumented)
237235
static ɵinj: i0.ɵɵInjectorDeclaration<MatMenuModule>;
238236
// (undocumented)
239-
static ɵmod: i0.ɵɵNgModuleDeclaration<MatMenuModule, [typeof i4.MatMenu, typeof i5.MatMenuItem], [typeof i6.CommonModule, typeof i3.MatCommonModule, typeof i3.MatRippleModule, typeof i7.OverlayModule, typeof _MatMenuDirectivesModule], [typeof i8.CdkScrollableModule, typeof i3.MatCommonModule, typeof i4.MatMenu, typeof i5.MatMenuItem, typeof _MatMenuDirectivesModule]>;
237+
static ɵmod: i0.ɵɵNgModuleDeclaration<MatMenuModule, [typeof i1.MatMenu, typeof i2.MatMenuItem, typeof i3.MatMenuTrigger, typeof i4.MatMenuContent], [typeof i5.CommonModule, typeof i6.MatCommonModule, typeof i6.MatRippleModule, typeof i7.OverlayModule], [typeof i8.CdkScrollableModule, typeof i6.MatCommonModule, typeof i1.MatMenu, typeof i2.MatMenuItem, typeof i3.MatMenuTrigger, typeof i4.MatMenuContent]>;
240238
}
241239

242240
// @public
@@ -280,8 +278,22 @@ export interface MatMenuPanel<T = any> {
280278
}
281279

282280
// @public
283-
export class MatMenuTrigger implements AfterContentInit, OnDestroy {
281+
export class MatMenuTrigger extends _MatMenuTriggerBase {
282+
// (undocumented)
283+
static ɵdir: i0.ɵɵDirectiveDeclaration<MatMenuTrigger, "[mat-menu-trigger-for], [matMenuTriggerFor]", ["matMenuTrigger"], {}, {}, never>;
284+
// (undocumented)
285+
static ɵfac: i0.ɵɵFactoryDeclaration<MatMenuTrigger, never>;
286+
}
287+
288+
// @public (undocumented)
289+
export abstract class _MatMenuTriggerBase implements AfterContentInit, OnDestroy {
284290
constructor(_overlay: Overlay, _element: ElementRef<HTMLElement>, _viewContainerRef: ViewContainerRef, scrollStrategy: any, parentMenu: MatMenuPanel, _menuItemInstance: MatMenuItem, _dir: Directionality, _focusMonitor?: FocusMonitor | undefined);
291+
// (undocumented)
292+
get _ariaControl(): string | null | undefined;
293+
// (undocumented)
294+
get _ariaExpanded(): true | null;
295+
// (undocumented)
296+
_ariaHaspopup: boolean;
285297
closeMenu(): void;
286298
// @deprecated (undocumented)
287299
get _deprecatedMatMenuTriggerFor(): MatMenuPanel;
@@ -313,9 +325,9 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
313325
triggersSubmenu(): boolean;
314326
updatePosition(): void;
315327
// (undocumented)
316-
static ɵdir: i0.ɵɵDirectiveDeclaration<MatMenuTrigger, "[mat-menu-trigger-for], [matMenuTriggerFor]", ["matMenuTrigger"], { "_deprecatedMatMenuTriggerFor": "mat-menu-trigger-for"; "menu": "matMenuTriggerFor"; "menuData": "matMenuTriggerData"; "restoreFocus": "matMenuTriggerRestoreFocus"; }, { "menuOpened": "menuOpened"; "onMenuOpen": "onMenuOpen"; "menuClosed": "menuClosed"; "onMenuClose": "onMenuClose"; }, never>;
328+
static ɵdir: i0.ɵɵDirectiveDeclaration<_MatMenuTriggerBase, never, never, { "_deprecatedMatMenuTriggerFor": "mat-menu-trigger-for"; "menu": "matMenuTriggerFor"; "menuData": "matMenuTriggerData"; "restoreFocus": "matMenuTriggerRestoreFocus"; }, { "menuOpened": "menuOpened"; "onMenuOpen": "onMenuOpen"; "menuClosed": "menuClosed"; "onMenuClose": "onMenuClose"; }, never>;
317329
// (undocumented)
318-
static ɵfac: i0.ɵɵFactoryDeclaration<MatMenuTrigger, [null, null, null, null, { optional: true; }, { optional: true; self: true; }, { optional: true; }, null]>;
330+
static ɵfac: i0.ɵɵFactoryDeclaration<_MatMenuTriggerBase, [null, null, null, null, { optional: true; }, { optional: true; self: true; }, { optional: true; }, null]>;
319331
}
320332

321333
// @public

0 commit comments

Comments
 (0)