Routed tabs
Some references ship a separate tab-nav-bar component for router-driven tabs. <oge-tabs> needs no variant: bind selectedKey one-way from the URL and navigate in selectionChanged. Keyboard support, overflow and closable tabs all keep working, and the panels come from <router-outlet> instead of the component.
router-outlet selectedKey deep links
Router-driven selection
The strip never owns the selection here — it reflects the active route and asks the router to change it. Because selectedKey is matched by key (not index), routes can be reordered or added without touching the binding.
URL is the source of truth Back/Forward works
Overview
Members4
Settings
Overview — rendered by the router into <router-outlet>, not by the tab strip.
import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
import { RouterOutlet, NavigationEnd, Router } from '@angular/router';
import { OgeTabs } from '@oge-ui/tabs';
import { toSignal } from '@angular/core/rxjs-interop';
import { filter, map } from 'rxjs';
import type { OgeTabItem, OgeTabSelectionChangedEvent } from '@oge-ui/tabs';
@Component({
selector: 'demo-root',
imports: [RouterOutlet, OgeTabs],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<oge-tabs
[items]="tabs"
[selectedKey]="activeKey()"
(selectionChanged)="go($event)"
ariaLabel="Project sections"
/>
<router-outlet />
`,
})
export class Demo {
protected readonly tabs: OgeTabItem[] = [
{ key: 'overview', text: 'Overview' },
{ key: 'activity', text: 'Activity' },
{ key: 'settings', text: 'Settings' },
];
// the URL is the single source of truth
private readonly router = inject(Router);
private readonly url = toSignal(
this.router.events.pipe(
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
map((e) => e.urlAfterRedirects),
),
{ initialValue: this.router.url },
);
protected readonly activeKey = computed(() => {
const segment = this.url().split(/[?#]/)[0].split('/').pop() ?? '';
return this.tabs.some((t) => t.key === segment) ? segment : 'overview';
});
protected go(event: OgeTabSelectionChangedEvent): void {
if (event.key) {
void this.router.navigate(['/components/tabs/routed', event.key]);
}
}
}