Angular CDK: Context Menu personalizado
Context Menu o Menú Contextual
Es posible que alguna vez te hayas preguntado si el menú con opciones que sale cuando haces click derecho en algún lugar de una web se puede personalizar. Y la respuesta es Sí.
Desde la llegada de la versión 14 de Angular tenemos disponible el módulo Menu en el CDK. Éste nos permitirá crear una multitud de diferentes de menús, y entre ellos, el menú contextual.
Tecnologías
El stack de versiones que se usarán para el desarrollo del proyecto es el siguiente.
- Angular CLI (15.0.0)
- Node (16.18.1)
- Npm (9.1.2)
- Typescript (4.8.4)
Objetivo
Vamos a crear una aplicación sencilla con unos cards de ejemplo, en los cuales el botón derecho mostrará un menú contextual personalizado.
Creando la aplicación
Abrimos el terminal y ejecutamos el siguiente comando para crear una aplicación básica en Angular.
ng new custom-context-menu --minimal true --style scss --routing false
Seguidamente añadimos Angular Material a nuestro proyecto.
ng add @angular/material
Creamos un componente sencillo de un dashboard a partir de una plantilla de Schematics.
ng generate @angular/material:dashboard components/dashboard
Ahora vamos a cambiar el template del componente app.component.ts para que muestre el nuevo componente.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-dashboard></app-dashboard>
`,
styles: []
})
export class AppComponent {
title = 'custom-context-menu';
}
Podemos compilar la aplicación para ver cómo lo llevamos hasta ahora.
ng serve -o
Implementando el Context Menu
Para usar la directiva que se encarga de que podamos implementar un menú contextual personalizado tenemos que importar el módulo CdkMenuModule en el archivo app.module.ts.
app.module.ts
import { CdkMenuModule } from '@angular/cdk/menu';
@NgModule({
declarations: [ ... ],
imports: [
...
CdkMenuModule
],
providers: [],
bootstrap: [ ... ]
})
export class AppModule { }
Ahora implementaremos la directiva
Para ello crearemos un menú sencillo con 3 opciones dentro de un ng-template. Le daremos estilo. Y crearemos unas funciones de ejemplo para comprobar que los botones del menú funcionan.
dashboard.component.ts
@Component({
selector: 'app-dashboard',
template: `
<div class="grid-container">
<h1 class="mat-h1">Dashboard</h1>
<mat-grid-list cols="2" rowHeight="350px">
<mat-grid-tile *ngFor="let card of cards | async" [colspan]="card.cols" [rowspan]="card.rows">
<mat-card class="dashboard-card" [cdkContextMenuTriggerFor]="context_menu">
...
</mat-card>
<!-- Context Menu -->
<ng-template #context_menu>
<div class="context-menu mat-elevation-z8" cdkMenu>
<button class="context-menu-item" cdkMenuItem (click)="cut()">Cut</button>
<button class="context-menu-item" cdkMenuItem (click)="copy()">Copy</button>
<button class="context-menu-item" cdkMenuItem (click)="link()">Link</button>
</div>
</ng-template>
</mat-grid-tile>
</mat-grid-list>
</div>
`,
styles: [`
...
/* Context Menu */
.context-menu {
display: inline-flex;
flex-direction: column;
min-width: 180px;
max-width: 280px;
background-color: rgb(255, 255, 255);
padding: 6px 0;
border-radius: 4px;
}
.context-menu-item {
background-color: transparent;
cursor: pointer;
border: none;
user-select: none;
min-width: 64px;
line-height: 36px;
padding: 0 16px;
display: flex;
align-items: center;
flex-direction: row;
flex: 1;
}
.context-menu-item:hover {
background-color: rgb(208, 208, 208);
}
.context-menu-item:active {
background-color: rgb(170, 170, 170);
}
`]
})
export class DashboardComponent {
...
constructor(private breakpointObserver: BreakpointObserver) {}
/**
* Do whatever you want
*/
cut(): void {
console.log('Acción de cortar');
}
/**
* Do whatever you want
*/
copy(): void {
console.log('Acción de copiar');
}
/**
* Do whatever you want
*/
link(): void {
console.log('Acción de ir a un enlace');
}
}
Resultado
Llegados a este punto, si compilamos el proyecto ejecutando el comando ng serve -o en la terminal se nos abrirá en el navegador y veremos el resultado.
Ya podríamos comprobar cómo al hacer click derecho encima de los cards nos abre el menú que hemos creado. Y si, por el contrario, hacemos click derecho entre los cards o en otro sitio, vemos el menú contextual por defecto. Además, en la consola vemos el texto que imprimen los console.log de nuestros botones.
Stackblitz
A continuación, tenéis el proyecto en Stackblitz para poder toquetear y hacer pruebas en vivo con él 😉
Analyst Frontend Developer en Comunytek (BBVA CIB – NOVA).
Autodidacta, apasionado de las nuevas tecnologías y de los proyectos DIY.