ngx-role-menu
v2.1.4
Published
Componente Angular reutilizable para menús basados en roles de usuario
Downloads
20
Maintainers
Readme
ngx-role-menu
Componente Angular reutilizable para crear menús dinámicos basados en roles de usuario almacenados en localStorage.
📌 Compatibilidad
- ✅ Angular 16, 17, 18, 19 y 20
- ✅ TypeScript 5.2+
- ✅ RxJS 7.8+
- ✅ Standalone Component ⭐ NUEVO en v2.0
🚀 Características
- ✅ Componente Standalone - Uso directo sin NgModule
- ✅ Menús dinámicos basados en roles de usuario
- ✅ Almacenamiento de roles en localStorage
- ✅ Soporte para iconos (imágenes o clases CSS)
- ✅ Orientación horizontal y vertical
- ✅ Totalmente personalizable con clases CSS
- ✅ TypeScript con tipado completo
- ✅ Compatible con Angular Router
- ✅ Fácil de integrar en cualquier proyecto Angular
📦 Instalación
npm install ngx-role-menu🔧 Configuración
Opción 1: Uso Standalone (Recomendado) ⭐
Para aplicaciones modernas con Angular 14+:
import { Component } from '@angular/core';
import { RoleMenuComponent, RoleMenuConfig } from 'ngx-role-menu';
@Component({
selector: 'app-root',
standalone: true,
imports: [RoleMenuComponent],
template: '<ngx-role-menu [config]="menuConfig"></ngx-role-menu>'
})
export class AppComponent {
menuConfig: RoleMenuConfig = {
// ... configuración
};
}Opción 2: Uso con NgModule (Compatible con versiones anteriores)
En tu app.module.ts o el módulo donde quieras usar el componente:
import { NgxRoleMenuModule } from 'ngx-role-menu';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
RouterModule.forRoot([]),
NgxRoleMenuModule // Importar el módulo
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }Configuración del Menú
Crea tu configuración de menú por roles (funciona igual para standalone y NgModule):
import { Component } from '@angular/core';
import { RoleMenuConfig } from 'ngx-role-menu';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
menuConfig: RoleMenuConfig = {
localStorageKey: 'userRole', // Opcional, por defecto es 'userRole'
roles: [
{
roleName: 'admin',
menuItems: [
{
label: 'Dashboard',
link: '/admin/dashboard',
iconClass: 'fas fa-tachometer-alt'
},
{
label: 'Usuarios',
link: '/admin/users',
icon: 'https://example.com/icons/users.svg'
},
{
label: 'Configuración',
link: '/admin/settings',
iconClass: 'fas fa-cog'
},
{
label: 'Reportes',
link: '/admin/reports',
iconClass: 'fas fa-chart-bar'
}
]
},
{
roleName: 'user',
menuItems: [
{
label: 'Mi Perfil',
link: '/profile',
iconClass: 'fas fa-user'
},
{
label: 'Mis Pedidos',
link: '/orders',
iconClass: 'fas fa-shopping-cart'
},
{
label: 'Ayuda',
link: 'https://help.example.com',
iconClass: 'fas fa-question-circle',
openInNewTab: true
}
]
},
{
roleName: 'guest',
menuItems: [
{
label: 'Inicio',
link: '/',
iconClass: 'fas fa-home'
},
{
label: 'Login',
link: '/login',
iconClass: 'fas fa-sign-in-alt'
}
]
}
],
defaultMenu: [
{
label: 'Inicio',
link: '/',
iconClass: 'fas fa-home'
}
]
};
}Uso del Componente
En tu template HTML (funciona igual para standalone y NgModule):
<!-- Menú vertical (por defecto) -->
<ngx-role-menu [config]="menuConfig"></ngx-role-menu>
<!-- Menú horizontal -->
<ngx-role-menu
[config]="menuConfig"
orientation="horizontal">
</ngx-role-menu>
<!-- Con clases personalizadas -->
<ngx-role-menu
[config]="menuConfig"
menuClass="mi-menu-personalizado"
itemClass="mi-item-personalizado">
</ngx-role-menu>
<!-- Sin iconos -->
<ngx-role-menu
[config]="menuConfig"
[showIcons]="false">
</ngx-role-menu>🎯 Uso del Servicio
El paquete incluye un servicio RoleMenuService que puedes usar para gestionar los roles programáticamente:
Con Standalone Components
import { Component, OnInit } from '@angular/core';
import { RoleMenuComponent, RoleMenuService } from 'ngx-role-menu';
@Component({
selector: 'app-login',
standalone: true,
imports: [RoleMenuComponent],
templateUrl: './login.component.html'
})
export class LoginComponent implements OnInit {
constructor(private roleMenuService: RoleMenuService) {}
ngOnInit() {
// Obtener el rol actual
const currentRole = this.roleMenuService.getUserRole();
console.log('Rol actual:', currentRole);
}
onLogin(username: string, password: string) {
// Después de validar credenciales...
const userRole = 'admin'; // Obtenido de tu API
// Establecer el rol (actualiza automáticamente el menú)
this.roleMenuService.setUserRole(userRole);
}
onLogout() {
// Limpiar el rol del usuario
this.roleMenuService.clearUserRole();
}
}Con NgModule (tradicional)
import { Component, OnInit } from '@angular/core';
import { RoleMenuService } from 'ngx-role-menu';
@Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent implements OnInit {
constructor(private roleMenuService: RoleMenuService) {}
ngOnInit() {
// Obtener el rol actual
const currentRole = this.roleMenuService.getUserRole();
console.log('Rol actual:', currentRole);
}
onLogin(username: string, password: string) {
// Después de validar credenciales...
const userRole = 'admin'; // Obtenido de tu API
// Establecer el rol (actualiza automáticamente el menú)
this.roleMenuService.setUserRole(userRole);
}
onLogout() {
// Limpiar el rol del usuario
this.roleMenuService.clearUserRole();
}
checkRole() {
// Verificar si un rol existe
if (this.roleMenuService.roleExists('admin')) {
console.log('El rol admin existe');
}
// Obtener todos los roles disponibles
const roles = this.roleMenuService.getAvailableRoles();
console.log('Roles disponibles:', roles);
}
}🌟 Ventajas de Standalone Components
¿Por qué usar Standalone?
- ✅ Más Simple - No necesitas crear o importar NgModules
- ✅ Menos Código - Importa solo lo que necesitas
- ✅ Mejor Tree-Shaking - Bundles más pequeños
- ✅ Más Rápido - Menor tiempo de compilación
- ✅ Moderno - Enfoque recomendado por Angular desde v14+
Comparación de Código
Antes (NgModule):
// app.module.ts
import { NgModule } from '@angular/core';
import { NgxRoleMenuModule } from 'ngx-role-menu';
@NgModule({
imports: [NgxRoleMenuModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
// app.component.ts
@Component({
selector: 'app-root',
template: '<ngx-role-menu [config]="menuConfig"></ngx-role-menu>'
})
export class AppComponent { }Ahora (Standalone):
// app.component.ts
import { Component } from '@angular/core';
import { RoleMenuComponent } from 'ngx-role-menu';
@Component({
selector: 'app-root',
standalone: true,
imports: [RoleMenuComponent],
template: '<ngx-role-menu [config]="menuConfig"></ngx-role-menu>'
})
export class AppComponent { }¡Más simple, menos archivos! 🎉
Observables del Servicio
import { Component, OnInit } from '@angular/core';
import { RoleMenuService } from 'ngx-role-menu';
export class MyComponent implements OnInit {
constructor(private roleMenuService: RoleMenuService) {}
ngOnInit() {
// Suscribirse a cambios en el menú
this.roleMenuService.menuItems$.subscribe(items => {
console.log('Nuevos items del menú:', items);
});
// Suscribirse a cambios en el rol
this.roleMenuService.currentRole.subscribe(role => {
console.log('Rol actual:', role);
});
}
}📋 Interfaces
MenuItem
interface MenuItem {
label: string; // Texto del menú
link: string; // URL o ruta
icon?: string; // URL del icono (imagen)
iconClass?: string; // Clase CSS del icono (ej: Font Awesome)
openInNewTab?: boolean; // Abrir en nueva pestaña
metadata?: any; // Datos adicionales
}RoleConfig
interface RoleConfig {
roleName: string; // Nombre del rol
menuItems: MenuItem[]; // Items del menú para este rol
}RoleMenuConfig
interface RoleMenuConfig {
roles: RoleConfig[]; // Configuraciones por rol
localStorageKey?: string; // Clave del localStorage (default: 'userRole')
defaultMenu?: MenuItem[]; // Menú por defecto si no hay rol
}🎨 Personalización de Estilos
El componente usa clases CSS con el prefijo ngx-role-menu. Puedes sobrescribir estos estilos en tu CSS global:
/* Personalizar el contenedor del menú */
.ngx-role-menu {
background-color: #f8f9fa;
padding: 1rem;
}
/* Personalizar los links */
.ngx-role-menu__link {
color: #333;
font-weight: bold;
}
.ngx-role-menu__link:hover {
background-color: #007bff;
color: white;
}
/* Personalizar los iconos */
.ngx-role-menu__icon {
font-size: 1.5rem;
color: #007bff;
}
/* Estado activo */
.ngx-role-menu__link.active {
background-color: #28a745;
}Clases CSS disponibles:
.ngx-role-menu- Contenedor principal.ngx-role-menu--vertical- Menú vertical.ngx-role-menu--horizontal- Menú horizontal.ngx-role-menu__list- Lista del menú.ngx-role-menu__item- Item individual.ngx-role-menu__link- Enlace del item.ngx-role-menu__icon- Icono (clase CSS).ngx-role-menu__icon-img- Icono (imagen).ngx-role-menu__label- Texto del item
📱 Ejemplo Completo
Aplicación Standalone Moderna (Recomendado)
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes)
]
});
// app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { RoleMenuComponent, RoleMenuConfig, RoleMenuService } from 'ngx-role-menu';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, RoleMenuComponent],
template: `
<header>
<h1>Mi Aplicación</h1>
<ngx-role-menu
[config]="menuConfig"
orientation="horizontal"
menuClass="main-nav">
</ngx-role-menu>
</header>
<main>
<router-outlet></router-outlet>
</main>
<button (click)="changeRole('admin')">Login como Admin</button>
<button (click)="changeRole('user')">Login como Usuario</button>
<button (click)="logout()">Logout</button>
`
})
export class AppComponent {
menuConfig: RoleMenuConfig = {
roles: [
{
roleName: 'admin',
menuItems: [
{ label: 'Dashboard', link: '/dashboard', iconClass: 'fas fa-home' },
{ label: 'Usuarios', link: '/users', iconClass: 'fas fa-users' },
{ label: 'Settings', link: '/settings', iconClass: 'fas fa-cog' }
]
},
{
roleName: 'user',
menuItems: [
{ label: 'Perfil', link: '/profile', iconClass: 'fas fa-user' },
{ label: 'Pedidos', link: '/orders', iconClass: 'fas fa-shopping-cart' }
]
}
],
defaultMenu: [
{ label: 'Home', link: '/', iconClass: 'fas fa-home' }
]
};
constructor(private roleMenuService: RoleMenuService) {}
changeRole(role: string) {
this.roleMenuService.setUserRole(role);
}
logout() {
this.roleMenuService.clearUserRole();
}
}Aplicación con NgModule (Tradicional)
// app.component.ts
import { Component } from '@angular/core';
import { RoleMenuConfig, RoleMenuService } from 'ngx-role-menu';
@Component({
selector: 'app-root',
template: `
<header>
<h1>Mi Aplicación</h1>
<ngx-role-menu
[config]="menuConfig"
orientation="horizontal"
menuClass="main-nav">
</ngx-role-menu>
</header>
<main>
<router-outlet></router-outlet>
</main>
<button (click)="changeRole('admin')">Login como Admin</button>
<button (click)="changeRole('user')">Login como Usuario</button>
<button (click)="logout()">Logout</button>
`
})
export class AppComponent {
menuConfig: RoleMenuConfig = {
roles: [
{
roleName: 'admin',
menuItems: [
{ label: 'Dashboard', link: '/dashboard', iconClass: 'fas fa-home' },
{ label: 'Usuarios', link: '/users', iconClass: 'fas fa-users' },
{ label: 'Settings', link: '/settings', iconClass: 'fas fa-cog' }
]
},
{
roleName: 'user',
menuItems: [
{ label: 'Perfil', link: '/profile', iconClass: 'fas fa-user' },
{ label: 'Pedidos', link: '/orders', iconClass: 'fas fa-shopping-cart' }
]
}
],
defaultMenu: [
{ label: 'Home', link: '/', iconClass: 'fas fa-home' }
]
};
constructor(private roleMenuService: RoleMenuService) {}
changeRole(role: string) {
this.roleMenuService.setUserRole(role);
}
logout() {
this.roleMenuService.clearUserRole();
}
}🔒 LocalStorage
El componente usa localStorage para persistir el rol del usuario. Por defecto, usa la clave 'userRole', pero puedes personalizarla:
menuConfig: RoleMenuConfig = {
localStorageKey: 'miAplicacion_rol', // Clave personalizada
roles: [...]
};Para establecer el rol manualmente en localStorage:
localStorage.setItem('userRole', 'admin');🤝 Contribuir
Las contribuciones son bienvenidas. Por favor, abre un issue o pull request en el repositorio.
📄 Licencia
MIT © [Tu Nombre]
🐛 Reportar Bugs
Si encuentras algún bug, por favor repórtalo en el repositorio de GitHub.
⭐ Soporte
Si este paquete te fue útil, considera darle una estrella en GitHub.
