Routed breadcrumb
The breadcrumb takes no @angular/router dependency — no package in the suite does. Derive the trail from the URL, keep url crumbs real links (middle-click and copy-address work) and hand the primary click to the router with preventDefault. The last crumb is the current page: non-interactive, aria-current="page".
URL-derived trail aria-current no router dependency
Router-driven trail
The trail never owns state — it is computed from the route. Navigating deeper grows it; browser Back shrinks it.
URL is the source of truth Back/Forward works
Monthly — deep-linkable: this URL can be bookmarked and shared, and browser Back walks the trail with it.
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
import { OgeBreadcrumb } from '@oge-ui/navigation';
import { RouterOutlet, NavigationEnd, Router } from '@angular/router';
import type { OgeBreadcrumbItemData, OgeBreadcrumbItemClickEvent } from '@oge-ui/navigation';
@Component({
selector: 'demo-root',
imports: [OgeBreadcrumb, RouterOutlet],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- The breadcrumb takes no router dependency: derive the trail
from the URL, keep url crumbs real links (middle-click works) and hand
the primary click to the router with preventDefault. The last crumb is
the current page — non-interactive with aria-current="page". -->
<oge-breadcrumb [items]="trail()" (itemClick)="go($event)" />
<router-outlet />
`,
})
export class Demo {
private readonly router = inject(Router);
private readonly url = signal(this.router.url);
/** One crumb per URL segment — the last one is the current page. */
protected readonly trail = computed<OgeBreadcrumbItemData[]>(() => {
const segments = this.url().split(/[?#]/)[0].split('/').filter(Boolean);
return segments.map((segment, index) => ({
text: segment,
key: segment,
url: '/' + segments.slice(0, index + 1).join('/'),
}));
});
constructor() {
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) this.url.set(event.urlAfterRedirects);
});
}
protected go(event: OgeBreadcrumbItemClickEvent): void {
event.event.preventDefault();
if (event.item.url) void this.router.navigateByUrl(event.item.url);
}
}