mo-breadcrumb-manager
Version:
Angular dynamic breadcrumb component with route-based navigation
220 lines (214 loc) • 8.19 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component } from '@angular/core';
import { BehaviorSubject, filter, Subject, takeUntil } from 'rxjs';
import * as i1 from '@angular/router';
import { NavigationEnd } from '@angular/router';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
class Breadcrumb {
router;
activatedRoute;
breadcrumbSubject = new BehaviorSubject([]);
pageTitleSubject = new BehaviorSubject('');
constructor(router, activatedRoute) {
this.router = router;
this.activatedRoute = activatedRoute;
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(() => {
this.updateBreadcrumbs();
});
}
get breadcrumbs$() {
return this.breadcrumbSubject.asObservable();
}
get pageTitle$() {
return this.pageTitleSubject.asObservable();
}
updateBreadcrumbs() {
const breadcrumbs = this.getBreadcrumbItems();
const pageTitle = this.getPageTitle();
this.breadcrumbSubject.next(breadcrumbs);
this.pageTitleSubject.next(pageTitle);
}
getPageTitle() {
let route = this.activatedRoute.snapshot;
while (route.firstChild) {
route = route.firstChild;
}
return route.data['title'] || '';
}
getBreadcrumbItems() {
const breadcrumbItems = [];
let route = this.activatedRoute.snapshot;
let url = '';
while (route) {
if (route.url.length > 0) {
url += '/' + route.url.map((segment) => segment.path).join('/');
}
if (route.data['breadcrumb']) {
const label = route.data['breadcrumb'];
const shouldExclude = (label.match(/-/g) || []).length >= 3;
if (!shouldExclude) {
breadcrumbItems.push({
label: label,
url: url,
isClickable: true,
});
}
}
route = route.firstChild;
}
return breadcrumbItems;
}
navigateTo(item) {
if (item.isClickable && item.url) {
this.router.navigate([item.url]);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Breadcrumb, deps: [{ token: i1.Router }, { token: i1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Breadcrumb, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Breadcrumb, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: i1.Router }, { type: i1.ActivatedRoute }] });
class MoBreadcumbManager {
breadcrumbService;
breadcrumbItems = [];
pageTitle = '';
destroy$ = new Subject();
constructor(breadcrumbService) {
this.breadcrumbService = breadcrumbService;
}
ngOnInit() {
this.breadcrumbService.breadcrumbs$
.pipe(takeUntil(this.destroy$))
.subscribe((items) => (this.breadcrumbItems = items));
this.breadcrumbService.pageTitle$
.pipe(takeUntil(this.destroy$))
.subscribe((title) => (this.pageTitle = title));
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
onBreadcrumbClick(item) {
this.breadcrumbService.navigateTo(item);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: MoBreadcumbManager, deps: [{ token: Breadcrumb }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: MoBreadcumbManager, isStandalone: true, selector: "mo-breadcrumb-manager", ngImport: i0, template: `
<div class="flex flex-col gap-1">
<nav class="flex flex-col" aria-label="Breadcrumb">
@if (pageTitle) {
<p class="text-sm md:text-xl font-bold my-2">{{ pageTitle }}</p>
}
<ol
class="inline-flex items-center space-x-1 md:space-x-2 rtl:space-x-reverse"
>
@for (item of breadcrumbItems; track $index; let first = $first; let
last = $last) {
<li class="inline-flex items-center text-xs">
<span
class="inline-flex items-center transition-colors duration-200"
[ngClass]="{
'!text-primary cursor-pointer hover:text-primary-dark':
first && item.isClickable,
'text-gray-600 cursor-pointer hover:text-gray-800':
!first && item.isClickable && !last,
'text-black font-semibold cursor-default':
!item.isClickable || last
}"
(click)="onBreadcrumbClick(item)"
>
{{ item.label }}
</span>
@if (!last) {
<svg
class="rtl:rotate-180 w-2 h-2 text-gray-700 mx-1"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 6 10"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 9 4-4-4-4"
/>
</svg>
}
</li>
}
</ol>
</nav>
</div>
`, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: MoBreadcumbManager, decorators: [{
type: Component,
args: [{ selector: 'mo-breadcrumb-manager', imports: [CommonModule], template: `
<div class="flex flex-col gap-1">
<nav class="flex flex-col" aria-label="Breadcrumb">
@if (pageTitle) {
<p class="text-sm md:text-xl font-bold my-2">{{ pageTitle }}</p>
}
<ol
class="inline-flex items-center space-x-1 md:space-x-2 rtl:space-x-reverse"
>
@for (item of breadcrumbItems; track $index; let first = $first; let
last = $last) {
<li class="inline-flex items-center text-xs">
<span
class="inline-flex items-center transition-colors duration-200"
[ngClass]="{
'!text-primary cursor-pointer hover:text-primary-dark':
first && item.isClickable,
'text-gray-600 cursor-pointer hover:text-gray-800':
!first && item.isClickable && !last,
'text-black font-semibold cursor-default':
!item.isClickable || last
}"
(click)="onBreadcrumbClick(item)"
>
{{ item.label }}
</span>
@if (!last) {
<svg
class="rtl:rotate-180 w-2 h-2 text-gray-700 mx-1"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 6 10"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 9 4-4-4-4"
/>
</svg>
}
</li>
}
</ol>
</nav>
</div>
` }]
}], ctorParameters: () => [{ type: Breadcrumb }] });
/*
* Public API Surface of mo-breadcrumb-manager
*/
/*
* Public API Surface of ng-dynamic-breadcrumb
*/
/**
* Generated bundle index. Do not edit.
*/
export { Breadcrumb, MoBreadcumbManager };
//# sourceMappingURL=mo-breadcrumb-manager.mjs.map