Skip to content

Commit a2cf3f6

Browse files
authored
feat(cdk/menu): add support for passing in data to the menu template (#25778)
Adds the `cdkMenuTriggerData` and `cdkContextMenuTriggerData` inputs that allow the consumer of a CDK menu to pass context data to the menu template. Fixes #25708.
1 parent a2b3968 commit a2cf3f6

File tree

6 files changed

+76
-5
lines changed

6 files changed

+76
-5
lines changed

src/cdk/menu/context-menu-trigger.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,21 @@ describe('CdkContextMenuTrigger', () => {
422422
expect(fixture.componentInstance.menus.length).toBe(1);
423423
});
424424
});
425+
426+
it('should be able to pass data to the menu via the template context', () => {
427+
TestBed.configureTestingModule({
428+
imports: [CdkMenuModule],
429+
declarations: [ContextTriggerWithData],
430+
}).compileComponents();
431+
432+
const fixture = TestBed.createComponent(ContextTriggerWithData);
433+
fixture.componentInstance.menuData = {message: 'Hello!'};
434+
fixture.detectChanges();
435+
dispatchMouseEvent(fixture.componentInstance.triggerElement.nativeElement, 'contextmenu');
436+
fixture.detectChanges();
437+
438+
expect(document.querySelector('.test-menu')?.textContent).toBe('Hello!');
439+
});
425440
});
426441

427442
@Component({
@@ -552,3 +567,17 @@ class MenuBarAndContextTriggerShareMenu {
552567
@ViewChild(CdkContextMenuTrigger) contextTrigger: CdkContextMenuTrigger;
553568
@ViewChildren(CdkMenu) menus: QueryList<CdkMenu>;
554569
}
570+
571+
@Component({
572+
template: `
573+
<div [cdkContextMenuTriggerFor]="context" [cdkContextMenuTriggerData]="menuData"></div>
574+
575+
<ng-template #context let-message="message">
576+
<div cdkMenu class="test-menu">{{message}}</div>
577+
</ng-template>
578+
`,
579+
})
580+
class ContextTriggerWithData {
581+
@ViewChild(CdkContextMenuTrigger, {read: ElementRef}) triggerElement: ElementRef<HTMLElement>;
582+
menuData: unknown;
583+
}

src/cdk/menu/context-menu-trigger.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ export type ContextMenuCoordinates = {x: number; y: number};
6161
'[attr.data-cdk-menu-stack-id]': 'null',
6262
'(contextmenu)': '_openOnContextMenu($event)',
6363
},
64-
inputs: ['menuTemplateRef: cdkContextMenuTriggerFor', 'menuPosition: cdkContextMenuPosition'],
64+
inputs: [
65+
'menuTemplateRef: cdkContextMenuTriggerFor',
66+
'menuPosition: cdkContextMenuPosition',
67+
'menuData: cdkContextMenuTriggerData',
68+
],
6569
outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'],
6670
providers: [
6771
{provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger},

src/cdk/menu/menu-trigger-base.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ export abstract class CdkMenuTriggerBase implements OnDestroy {
6060
/** Template reference variable to the menu this trigger opens */
6161
menuTemplateRef: TemplateRef<unknown>;
6262

63+
/** Context data to be passed along to the menu template */
64+
menuData: unknown;
65+
6366
/** A reference to the overlay which manages the triggered menu */
6467
protected overlayRef: OverlayRef | null = null;
6568

@@ -105,7 +108,7 @@ export abstract class CdkMenuTriggerBase implements OnDestroy {
105108
this._menuPortal = new TemplatePortal(
106109
this.menuTemplateRef,
107110
this.viewContainerRef,
108-
undefined,
111+
this.menuData,
109112
this._getChildMenuInjector(),
110113
);
111114
}

src/cdk/menu/menu-trigger.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,21 @@ describe('MenuTrigger', () => {
454454
expect(nativeMenus.length).toBe(1);
455455
});
456456
});
457+
458+
it('should be able to pass data to the menu via the template context', () => {
459+
TestBed.configureTestingModule({
460+
imports: [CdkMenuModule],
461+
declarations: [TriggerWithData],
462+
}).compileComponents();
463+
464+
const fixture = TestBed.createComponent(TriggerWithData);
465+
fixture.componentInstance.menuData = {message: 'Hello!'};
466+
fixture.detectChanges();
467+
fixture.nativeElement.querySelector('button').click();
468+
fixture.detectChanges();
469+
470+
expect(document.querySelector('.test-menu')?.textContent).toBe('Hello!');
471+
});
457472
});
458473

459474
@Component({
@@ -572,3 +587,18 @@ class StandaloneTriggerWithInlineMenu {
572587
@ViewChild('inline_item', {read: ElementRef}) nativeInlineItem: ElementRef<HTMLElement>;
573588
@ViewChildren(CdkMenu, {read: ElementRef}) nativeMenus: QueryList<ElementRef>;
574589
}
590+
591+
@Component({
592+
template: `
593+
<button
594+
[cdkMenuTriggerFor]="menu"
595+
[cdkMenuTriggerData]="menuData">Click me!</button>
596+
597+
<ng-template #menu let-message="message">
598+
<div cdkMenu class="test-menu">{{message}}</div>
599+
</ng-template>
600+
`,
601+
})
602+
class TriggerWithData {
603+
menuData: unknown;
604+
}

src/cdk/menu/menu-trigger.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ import {CdkMenuTriggerBase, MENU_TRIGGER} from './menu-trigger-base';
5151
'(keydown)': '_toggleOnKeydown($event)',
5252
'(click)': 'toggle()',
5353
},
54-
inputs: ['menuTemplateRef: cdkMenuTriggerFor', 'menuPosition: cdkMenuPosition'],
54+
inputs: [
55+
'menuTemplateRef: cdkMenuTriggerFor',
56+
'menuPosition: cdkMenuPosition',
57+
'menuData: cdkMenuTriggerData',
58+
],
5559
outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'],
5660
providers: [
5761
{provide: MENU_TRIGGER, useExisting: CdkMenuTrigger},

tools/public_api_guard/cdk/menu.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr
4040
open(coordinates: ContextMenuCoordinates): void;
4141
_openOnContextMenu(event: MouseEvent): void;
4242
// (undocumented)
43-
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkContextMenuTrigger, "[cdkContextMenuTriggerFor]", ["cdkContextMenuTriggerFor"], { "menuTemplateRef": "cdkContextMenuTriggerFor"; "menuPosition": "cdkContextMenuPosition"; "disabled": "cdkContextMenuDisabled"; }, { "opened": "cdkContextMenuOpened"; "closed": "cdkContextMenuClosed"; }, never, never, false, never>;
43+
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkContextMenuTrigger, "[cdkContextMenuTriggerFor]", ["cdkContextMenuTriggerFor"], { "menuTemplateRef": "cdkContextMenuTriggerFor"; "menuPosition": "cdkContextMenuPosition"; "menuData": "cdkContextMenuTriggerData"; "disabled": "cdkContextMenuDisabled"; }, { "opened": "cdkContextMenuOpened"; "closed": "cdkContextMenuClosed"; }, never, never, false, never>;
4444
// (undocumented)
4545
static ɵfac: i0.ɵɵFactoryDeclaration<CdkContextMenuTrigger, never>;
4646
}
@@ -203,7 +203,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnDestroy {
203203
toggle(): void;
204204
_toggleOnKeydown(event: KeyboardEvent): void;
205205
// (undocumented)
206-
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkMenuTrigger, "[cdkMenuTriggerFor]", ["cdkMenuTriggerFor"], { "menuTemplateRef": "cdkMenuTriggerFor"; "menuPosition": "cdkMenuPosition"; }, { "opened": "cdkMenuOpened"; "closed": "cdkMenuClosed"; }, never, never, false, never>;
206+
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkMenuTrigger, "[cdkMenuTriggerFor]", ["cdkMenuTriggerFor"], { "menuTemplateRef": "cdkMenuTriggerFor"; "menuPosition": "cdkMenuPosition"; "menuData": "cdkMenuTriggerData"; }, { "opened": "cdkMenuOpened"; "closed": "cdkMenuClosed"; }, never, never, false, never>;
207207
// (undocumented)
208208
static ɵfac: i0.ɵɵFactoryDeclaration<CdkMenuTrigger, never>;
209209
}
@@ -217,6 +217,7 @@ export abstract class CdkMenuTriggerBase implements OnDestroy {
217217
readonly injector: Injector;
218218
protected isElementInsideMenuStack(element: Element): boolean;
219219
isOpen(): boolean;
220+
menuData: unknown;
220221
menuPosition: ConnectedPosition[];
221222
protected readonly menuStack: MenuStack;
222223
menuTemplateRef: TemplateRef<unknown>;

0 commit comments

Comments
 (0)