Este manual describe cómo implementar el patrón de navegación "Espacios de Trabajo" utilizando los componentes y servicios de la librería Nébula UI Kit.
En aplicaciones ERP complejas, un usuario suele trabajar en múltiples tareas a la vez dentro de un mismo módulo (ej: ver un listado de facturas y editar una factura específica).
Nébula gestiona esto mediante:
El NebulaNavigationService debe proveerse de forma global (root) para mantener el estado entre cambios de ruta.
// app.config.ts
import { NebulaNavigationService } from 'nebula-ui-kit';
export const appConfig: ApplicationConfig = {
providers: [
NebulaNavigationService,
// ... otros proveedores
]
};
Puedes personalizar dónde y cómo se guarda la sesión mediante el token NEBULA_UI_CONFIG.
{
provide: NEBULA_UI_CONFIG,
useValue: {
navStorageKey: 'mi_app_nav_v1', // Nombre en localStorage
encryptionKey: 'clave-secreta' // Habilita cifrado XOR de la sesión
}
}
nebulaTabGuardPara evitar que un usuario acceda a una URL profunda mediante un marcador o refresco de página sin que la pestaña esté correctamente inicializada, usamos el nebulaTabGuard.
[!IMPORTANT]
Si el usuario tiene unAuthGuard, este debe ejecutarse antes que el guard de Nébula.
// app.routes.ts
import { nebulaTabGuard } from 'nebula-ui-kit';
export const routes: Routes = [
{
path: 'contabilidad',
canActivate: [authGuard, nebulaTabGuard],
children: [
{ path: 'libro-mayor', component: LedgerComponent },
{ path: 'facturas/:id', component: InvoiceDetailComponent }
]
}
];
Nébula utiliza un modelo de Sincronización Automática. El SidebarComponent y el TabsComponent detectan el servicio por su cuenta.
Solo necesitas colocar los componentes. No es estrictamente necesario pasarle inputs si usas el servicio global.
<!-- main-layout.component.html -->
<lib-sidebar [menuItems]="menu()" />
<main>
<lib-tabs />
<router-outlet />
</main>
Si necesitas abrir pestañas por código o gestionar lógica personalizada, inyecta el servicio:
export class MainLayout {
private navService = inject(NebulaNavigationService);
abrirReporte(id: string) {
this.navService.addTabFromMenu({
id: `reporte-${id}`,
label: 'Reporte Mensual',
route: `/contabilidad/reportes/${id}`,
icon: 'description'
});
}
}
El servicio detecta automáticamente el "Contexto" basado en la URL (ej: /modulo-a/ vs /modulo-b/). Cada contexto tiene su propio set de pestañas independiente.
Si se proporciona una encryptionKey, el JSON guardado en localStorage estará ofuscado. Esto previene que usuarios malintencionados o otras pestañas del mismo dominio lean fácilmente qué rutas tiene abiertas el usuario.
[!TIP]
Para una integración fluida, asegúrate de que todos losMenuItempasados al Sidebar tengan una propiedadrouteque coincida exactamente con la ruta definida en tuAppRoutes.
Para que el sistema de navegación funcione correctamente en Nébula, es fundamental mantener una consistencia estricta entre los MenuItem del Sidebar y la configuración de rutas (AppRoutes).
Cada elemento del menú debe tener una propiedad route que coincida exactamente con una ruta válida definida en el router de Angular.
export const routes: Routes = [
{
path: 'contabilidad',
children: [
{ path: 'libro-mayor', component: LedgerComponent },
{ path: 'facturas/:id', component: InvoiceDetailComponent }
]
}
];
menu = signal([
{
label: 'Libro Mayor',
route: '/contabilidad/libro-mayor',
icon: 'account_balance'
}
]);
{
label: 'Libro Mayor',
route: '/libro-mayor' // ❌ No coincide con la ruta real
}
Esto provocará:
NebulaNavigationServiceCuando un usuario hace clic en un ítem del Sidebar:
SidebarComponent emite el evento de navegaciónNebulaNavigationService intercepta la acciónTab) asociada a esa rutaTabsComponent se sincroniza automáticamenteSi la ruta no coincide:
app.routes.ts)/modulo/...) en el Sidebar:id, :slug, etc.)Define un archivo de constantes para rutas:
export const APP_ROUTES = {
CONTABILIDAD: {
LIBRO_MAYOR: '/contabilidad/libro-mayor'
}
};
Y úsalo en el Sidebar:
route: APP_ROUTES.CONTABILIDAD.LIBRO_MAYOR
Esto reduce errores y mejora la mantenibilidad del sistema.