Comprehensive Angular UI component library with 80+ components for building modern web applications
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
PrimeNG provides 12 comprehensive navigation components for building menus, breadcrumbs, tabs, and step indicators to guide users through your application.
Horizontal navigation menu with multi-level support.
// Import
import { MenuBar } from 'primeng/menubar';
// Module: MenubarModule
// Component Interface
interface MenuBarProps {
model?: MenuItem[];
style?: any;
styleClass?: string;
autoZIndex?: boolean;
baseZIndex?: number;
autoDisplay?: boolean;
autoHide?: boolean;
autoHideDelay?: number;
}
// Usage
@Component({
template: `
<p-menubar [model]="items">
<ng-template pTemplate="start">
<img src="assets/showcase/images/logo.svg" height="40" class="mr-2">
</ng-template>
<ng-template pTemplate="end">
<input type="text" pInputText placeholder="Search" class="w-full sm:w-auto">
</ng-template>
</p-menubar>
`
})
export class MenuBarComponent implements OnInit {
items: MenuItem[] = [];
ngOnInit() {
this.items = [
{
label: 'File',
icon: 'pi pi-fw pi-file',
items: [
{
label: 'New',
icon: 'pi pi-fw pi-plus',
items: [
{ label: 'Project' },
{ label: 'Other' }
]
},
{ label: 'Open' },
{ separator: true },
{ label: 'Quit' }
]
},
{
label: 'Edit',
icon: 'pi pi-fw pi-pencil',
items: [
{ label: 'Delete', icon: 'pi pi-fw pi-trash' },
{ label: 'Refresh', icon: 'pi pi-fw pi-refresh' }
]
},
{
label: 'Help',
icon: 'pi pi-fw pi-question',
items: [
{
label: 'Contents'
},
{
label: 'Search',
icon: 'pi pi-fw pi-search',
items: [
{
label: 'Text',
items: [
{ label: 'Workspace' }
]
},
{ label: 'File' }
]
}
]
}
];
}
}Vertical popup menu component.
// Import
import { Menu } from 'primeng/menu';
// Module: MenuModule
// Component Interface
interface MenuProps {
model?: MenuItem[];
popup?: boolean;
style?: any;
styleClass?: string;
appendTo?: any;
autoZIndex?: boolean;
baseZIndex?: number;
showTransitionOptions?: string;
hideTransitionOptions?: string;
ariaLabel?: string;
ariaLabelledBy?: string;
}
// Usage
@Component({
template: `
<p-toast></p-toast>
<p-menu #menu [model]="items" [popup]="true"></p-menu>
<button type="button" pButton icon="pi pi-bars" label="Show" (click)="menu.toggle($event)"></button>
<!-- Inline Menu -->
<p-menu [model]="items"></p-menu>
`
})
export class MenuComponent implements OnInit {
items: MenuItem[] = [];
ngOnInit() {
this.items = [
{ label: 'New', icon: 'pi pi-plus', command: () => this.messageService.add({severity:'success', summary:'Success', detail:'File Created'}) },
{ label: 'Open', icon: 'pi pi-download', url: 'http://primetek.com.tr' },
{ separator: true },
{ label: 'Export', icon: 'pi pi-external-link', routerLink: ['/fileupload'] }
];
}
}Multi-column dropdown menu for complex navigation.
// Import
import { MegaMenu } from 'primeng/megamenu';
// Module: MegaMenuModule
// Component Interface
interface MegaMenuProps {
model?: MegaMenuItem[];
orientation?: 'horizontal' | 'vertical';
style?: any;
styleClass?: string;
autoZIndex?: boolean;
baseZIndex?: number;
}
interface MegaMenuItem extends MenuItem {
columns?: MegaMenuColumn[];
}
interface MegaMenuColumn {
header?: string;
items?: MenuItem[];
}
// Usage
@Component({
template: `
<p-megamenu [model]="items"></p-megamenu>
`
})
export class MegaMenuComponent implements OnInit {
items: MegaMenuItem[] = [];
ngOnInit() {
this.items = [
{
label: 'TV',
icon: 'pi pi-fw pi-eye',
items: [
{
label: 'Submenu 1',
items: [
{ label: 'Submenu 1.1' },
{ label: 'Submenu 1.2' }
]
},
{
label: 'Submenu 2',
items: [
{ label: 'Submenu 2.1' },
{ label: 'Submenu 2.2' }
]
}
]
},
{
label: 'Sports',
items: [
{
label: 'Basketball',
items: [
{ label: 'NBA' },
{ label: 'Euroleague' }
]
},
{
label: 'Football',
items: [
{ label: 'Premier League' },
{ label: 'La Liga' }
]
}
]
}
];
}
}Nested popup menu with unlimited levels.
// Import
import { TieredMenu } from 'primeng/tieredmenu';
// Module: TieredMenuModule
// Component Interface
interface TieredMenuProps {
model?: MenuItem[];
popup?: boolean;
style?: any;
styleClass?: string;
appendTo?: any;
autoZIndex?: boolean;
baseZIndex?: number;
showTransitionOptions?: string;
hideTransitionOptions?: string;
ariaLabel?: string;
ariaLabelledBy?: string;
}
// Usage
@Component({
template: `
<p-tieredmenu #menu [model]="items" [popup]="true"></p-tieredmenu>
<button type="button" pButton icon="pi pi-bars" label="Show" (click)="menu.toggle($event)"></button>
`
})
export class TieredMenuComponent implements OnInit {
items: MenuItem[] = [];
ngOnInit() {
this.items = [
{
label: 'Customers',
icon: 'pi pi-fw pi-table',
items: [
{
label: 'New',
icon: 'pi pi-fw pi-user-plus',
items: [
{
label: 'Customer',
icon: 'pi pi-fw pi-plus'
},
{
label: 'Duplicate',
icon: 'pi pi-fw pi-copy'
}
]
},
{
label: 'Edit',
icon: 'pi pi-fw pi-user-edit'
}
]
}
];
}
}Right-click context menu.
// Import
import { ContextMenu } from 'primeng/contextmenu';
// Module: ContextMenuModule
// Component Interface
interface ContextMenuProps {
model?: MenuItem[];
global?: boolean;
target?: any;
style?: any;
styleClass?: string;
appendTo?: any;
autoZIndex?: boolean;
baseZIndex?: number;
showTransitionOptions?: string;
hideTransitionOptions?: string;
ariaLabel?: string;
ariaLabelledBy?: string;
}
// Usage
@Component({
template: `
<p-contextmenu #cm [model]="items"></p-contextmenu>
<!-- Global Context Menu -->
<p-contextmenu [global]="true" [model]="items"></p-contextmenu>
<!-- Target-specific Context Menu -->
<img #img src="assets/showcase/images/demo/nature/nature3.jpg" alt="Logo" (contextmenu)="cm.show($event)" style="width: 300px">
`
})
export class ContextMenuComponent implements OnInit {
items: MenuItem[] = [];
ngOnInit() {
this.items = [
{ label: 'View', icon: 'pi pi-fw pi-search' },
{ label: 'Delete', icon: 'pi pi-fw pi-times' }
];
}
}Collapsible menu with accordion-style panels.
// Import
import { PanelMenu } from 'primeng/panelmenu';
// Module: PanelMenuModule
// Component Interface
interface PanelMenuProps {
model?: MenuItem[];
style?: any;
styleClass?: string;
multiple?: boolean;
transitionOptions?: string;
id?: string;
}
// Usage
@Component({
template: `
<p-panelmenu [model]="items" [multiple]="true" styleClass="w-full md:w-20rem"></p-panelmenu>
`
})
export class PanelMenuComponent implements OnInit {
items: MenuItem[] = [];
ngOnInit() {
this.items = [
{
label: 'Mail',
icon: 'pi pi-fw pi-envelope',
items: [
{ label: 'Compose', icon: 'pi pi-fw pi-plus' },
{ label: 'Inbox', icon: 'pi pi-fw pi-inbox' },
{ label: 'Sent', icon: 'pi pi-fw pi-send' },
{ label: 'Trash', icon: 'pi pi-fw pi-trash' }
]
},
{
label: 'Reports',
icon: 'pi pi-fw pi-chart-bar',
items: [
{ label: 'Sales', icon: 'pi pi-fw pi-chart-line' },
{ label: 'Products', icon: 'pi pi-fw pi-list' }
]
}
];
}
}macOS-style dock menu with magnification effects.
// Import
import { Dock } from 'primeng/dock';
// Module: DockModule
// Component Interface
interface DockProps {
model?: MenuItem[];
position?: 'bottom' | 'top' | 'left' | 'right';
style?: any;
styleClass?: string;
tooltipOptions?: any;
}
// Usage
@Component({
template: `
<p-dock [model]="dockItems" position="bottom">
<ng-template pTemplate="item" let-item>
<img [src]="item.icon" [alt]="item.label" width="100%">
</ng-template>
</p-dock>
`
})
export class DockComponent implements OnInit {
dockItems: MenuItem[] = [];
ngOnInit() {
this.dockItems = [
{
label: 'Finder',
tooltipOptions: { tooltipLabel: 'Finder', tooltipPosition: 'top', positionLeft: 0, positionTop: -80 },
icon: 'assets/showcase/images/dock/finder.svg',
command: () => { this.displayFinder = true; }
},
{
label: 'Terminal',
tooltipOptions: { tooltipLabel: 'Terminal', tooltipPosition: 'top', positionLeft: 0, positionTop: -80 },
icon: 'assets/showcase/images/dock/terminal.svg',
command: () => { this.displayTerminal = true; }
}
];
}
}Navigation breadcrumb trail.
// Import
import { Breadcrumb } from 'primeng/breadcrumb';
// Module: BreadcrumbModule
// Component Interface
interface BreadcrumbProps {
model?: MenuItem[];
style?: any;
styleClass?: string;
home?: MenuItem;
}
// Usage
@Component({
template: `
<p-breadcrumb [model]="items" [home]="home"></p-breadcrumb>
`
})
export class BreadcrumbComponent implements OnInit {
items: MenuItem[] = [];
home: MenuItem = {};
ngOnInit() {
this.home = { icon: 'pi pi-home', routerLink: '/' };
this.items = [
{ label: 'Computer' },
{ label: 'Notebook' },
{ label: 'Accessories' },
{ label: 'Backpacks' },
{ label: 'Item' }
];
}
}Step indicator for multi-step processes.
// Import
import { Steps } from 'primeng/steps';
// Module: StepsModule
// Component Interface
interface StepsProps {
model?: MenuItem[];
activeIndex?: number;
readonly?: boolean;
style?: any;
styleClass?: string;
}
// Usage
@Component({
template: `
<div class="card">
<p-steps [model]="items" [activeIndex]="activeIndex" [readonly]="true"></p-steps>
</div>
<router-outlet></router-outlet>
<div class="flex pt-4 justify-content-between">
<p-button label="Back" (onClick)="prevPage()" icon="pi pi-angle-left" [disabled]="activeIndex === 0"></p-button>
<p-button label="Next" (onClick)="nextPage()" icon="pi pi-angle-right" iconPos="right" [disabled]="activeIndex === items.length - 1"></p-button>
</div>
`
})
export class StepsComponent implements OnInit {
items: MenuItem[] = [];
activeIndex: number = 0;
ngOnInit() {
this.items = [
{ label: 'Personal Info', routerLink: 'personal' },
{ label: 'Seat Selection', routerLink: 'seat' },
{ label: 'Payment', routerLink: 'payment' },
{ label: 'Confirmation', routerLink: 'confirmation' }
];
}
nextPage() {
this.activeIndex++;
}
prevPage() {
this.activeIndex--;
}
}Multi-step workflow component with content panels.
// Import
import { Stepper, StepperPanel } from 'primeng/stepper';
// Module: StepperModule
// Component Interface
interface StepperProps {
activeStep?: number;
orientation?: 'horizontal' | 'vertical';
linear?: boolean;
value?: any;
}
interface StepperPanelProps {
header?: string;
disabled?: boolean;
}
// Usage
@Component({
template: `
<p-stepper [(activeStep)]="active" styleClass="basis-50rem">
<p-stepperPanel header="Personal Info">
<ng-template pTemplate="content" let-nextCallback="nextCallback" let-index="index">
<div class="flex flex-column h-12rem">
<div class="border-2 border-dashed surface-border border-round surface-ground flex-auto flex justify-content-center align-items-center font-medium">Personal Information Content</div>
</div>
<div class="flex pt-4 justify-content-end">
<p-button label="Next" icon="pi pi-arrow-right" iconPos="right" (onClick)="nextCallback.emit()"></p-button>
</div>
</ng-template>
</p-stepperPanel>
<p-stepperPanel header="Seat Selection">
<ng-template pTemplate="content" let-prevCallback="prevCallback" let-nextCallback="nextCallback" let-index="index">
<div class="flex flex-column h-12rem">
<div class="border-2 border-dashed surface-border border-round surface-ground flex-auto flex justify-content-center align-items-center font-medium">Seat Selection Content</div>
</div>
<div class="flex pt-4 justify-content-between">
<p-button label="Back" severity="secondary" icon="pi pi-arrow-left" (onClick)="prevCallback.emit()"></p-button>
<p-button label="Next" icon="pi pi-arrow-right" iconPos="right" (onClick)="nextCallback.emit()"></p-button>
</div>
</ng-template>
</p-stepperPanel>
<p-stepperPanel header="Payment">
<ng-template pTemplate="content" let-prevCallback="prevCallback" let-nextCallback="nextCallback" let-index="index">
<div class="flex flex-column h-12rem">
<div class="border-2 border-dashed surface-border border-round surface-ground flex-auto flex justify-content-center align-items-center font-medium">Payment Information Content</div>
</div>
<div class="flex pt-4 justify-content-between">
<p-button label="Back" severity="secondary" icon="pi pi-arrow-left" (onClick)="prevCallback.emit()"></p-button>
<p-button label="Complete" icon="pi pi-arrow-right" iconPos="right" (onClick)="nextCallback.emit()"></p-button>
</div>
</ng-template>
</p-stepperPanel>
</p-stepper>
`
})
export class StepperComponent {
active: number = 0;
}Tab navigation with content panels.
// Import
import { Tabs, TabPanel } from 'primeng/tabs';
// Module: TabsModule
// Component Interface
interface TabsProps {
activeIndex?: number;
lazy?: boolean;
scrollable?: boolean;
showNavigators?: boolean;
buttonPrevIcon?: string;
buttonNextIcon?: string;
prevButtonAriaLabel?: string;
nextButtonAriaLabel?: string;
}
interface TabPanelProps {
header?: string;
headerTemplate?: TemplateRef<any>;
disabled?: boolean;
closable?: boolean;
selected?: boolean;
leftIcon?: string;
rightIcon?: string;
cache?: boolean;
tooltip?: string;
tooltipPosition?: string;
tooltipPositionStyle?: string;
tooltipStyleClass?: string;
}
// Events
interface TabChangeEvent {
originalEvent: Event;
index: number;
}
interface TabCloseEvent {
originalEvent: Event;
index: number;
close: Function;
}
// Usage
@Component({
template: `
<p-tabs [(activeIndex)]="activeIndex" (onChange)="onTabChange($event)">
<p-tabpanel header="Header I" leftIcon="pi pi-calendar">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</p-tabpanel>
<p-tabpanel header="Header II" rightIcon="pi pi-user">
<p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam,
eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo
enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui
ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</p-tabpanel>
<p-tabpanel header="Header III" leftIcon="pi pi-search">
<p>
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti
quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in
culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita
distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</p-tabpanel>
<p-tabpanel header="Header IV" [disabled]="true">
<p>
Disabled tab content.
</p>
</p-tabpanel>
</p-tabs>
`
})
export class TabsComponent {
activeIndex: number = 0;
onTabChange(event: TabChangeEvent) {
console.log('Tab changed:', event.index);
}
}Data pagination controls.
// Import
import { Paginator } from 'primeng/paginator';
// Module: PaginatorModule
// Component Interface
interface PaginatorProps {
totalRecords?: number;
rows?: number;
first?: number;
pageLinkSize?: number;
rowsPerPageOptions?: number[];
style?: any;
styleClass?: string;
alwaysShow?: boolean;
templateLeft?: TemplateRef<any>;
templateRight?: TemplateRef<any>;
dropdownAppendTo?: any;
dropdownScrollHeight?: string;
currentPageReportTemplate?: string;
showCurrentPageReport?: boolean;
showFirstLastIcon?: boolean;
totalRecordsText?: string;
showPageLinks?: boolean;
showJumpToPageDropdown?: boolean;
showJumpToPageInput?: boolean;
jumpToPageInputTooltip?: string;
showRowsPerPageDropdown?: boolean;
rowsPerPageDropdownTooltip?: string;
}
// Events
interface PageEvent {
first: number;
rows: number;
page: number;
pageCount: number;
}
// Usage
@Component({
template: `
<p-paginator
[first]="first"
[rows]="rows"
[totalRecords]="totalRecords"
[rowsPerPageOptions]="[10, 20, 30]"
[showCurrentPageReport]="true"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
[showJumpToPageDropdown]="true"
[showPageLinks]="true"
(onPageChange)="onPageChange($event)">
</p-paginator>
`
})
export class PaginatorComponent {
first: number = 0;
rows: number = 10;
totalRecords: number = 120;
onPageChange(event: PageEvent) {
this.first = event.first;
this.rows = event.rows;
}
}All navigation components use the standardized MenuItem interface:
interface MenuItem {
label?: string; // Display text
icon?: string; // Icon CSS class
command?: (event?: any) => void; // Click handler
url?: string; // External URL
routerLink?: any; // Angular router link
queryParams?: { [key: string]: any }; // Router query params
fragment?: string; // Router fragment
queryParamsHandling?: string; // Router query params handling
preserveFragment?: boolean; // Preserve URL fragment
skipLocationChange?: boolean; // Skip location change
replaceUrl?: boolean; // Replace URL
state?: { [key: string]: any }; // Router state
items?: MenuItem[]; // Submenu items
expanded?: boolean; // Expanded state
disabled?: boolean; // Disabled state
visible?: boolean; // Visibility state
target?: string; // Link target
separator?: boolean; // Separator item
badge?: string; // Badge text
badgeStyleClass?: string; // Badge CSS class
style?: any; // Inline styles
styleClass?: string; // CSS class
title?: string; // Tooltip text
id?: string; // Element ID
automationId?: any; // Automation ID
tabindex?: string; // Tab index
ariaLabel?: string; // ARIA label
columns?: MegaMenuColumn[]; // MegaMenu columns
}PrimeNG navigation components integrate seamlessly with Angular Router:
// Component
export class NavigationComponent implements OnInit {
items: MenuItem[] = [];
ngOnInit() {
this.items = [
{
label: 'Home',
icon: 'pi pi-home',
routerLink: ['/'],
queryParams: { tab: 'overview' }
},
{
label: 'Products',
icon: 'pi pi-box',
items: [
{
label: 'All Products',
routerLink: ['/products'],
queryParams: { category: 'all' }
},
{
label: 'Featured',
routerLink: ['/products'],
queryParams: { category: 'featured' }
}
]
},
{
label: 'External',
icon: 'pi pi-external-link',
url: 'https://www.primefaces.org/',
target: '_blank'
}
];
}
}All navigation components include comprehensive accessibility support:
Install with Tessl CLI
npx tessl i tessl/npm-primeng