File

app/shared/breadcrumb/breadcrumb.component.ts

Implements

OnChanges OnDestroy

Metadata

changeDetection ChangeDetectionStrategy.OnPush
selector div[breadcrumb]
styleUrls ./breadcrumb.component.scss
templateUrl ./breadcrumb.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(util: UtilService, dataService: DataResolverService, cdRef: ChangeDetectorRef, router: Router)
Parameters :
Name Type Optional
util UtilService No
dataService DataResolverService No
cdRef ChangeDetectorRef No
router Router No

Inputs

themeColor
Type : "light" | "dark"

Methods

Private buildBreadcrumb
buildBreadcrumb()

Builds breadcrumbs from navigation data

Returns : void
Public isClickable
isClickable(crumb)

Checks if the given breadcrumb is clickable

Parameters :
Name Optional
crumb No
Returns : boolean
ngOnChanges
ngOnChanges()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void

Properties

breadcrumbs
Type : []
Default value : []
navigation
showBreadcrumbs
Default value : true
subscription
import { Component, Input, OnChanges, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';
import { UtilService } from 'src/app/core/services/util-service/util.service';
import { DataResolverService } from 'src/app/core/services/data-resolver/data-resolver.service';
import { Router } from '@angular/router';

interface Crumb {
	title: string;
	url: string;
	metaData;
}

@Component ({
	selector: 'div[breadcrumb]',
	templateUrl: './breadcrumb.component.html',
	styleUrls: ['./breadcrumb.component.scss'],
	changeDetection: ChangeDetectionStrategy.OnPush
})
export class BreadcrumbComponent implements OnChanges, OnDestroy {

	@Input() themeColor: 'light' | 'dark';

	breadcrumbs = [];
	showBreadcrumbs = true;
	subscription;
	navigation;

	constructor(
		private util: UtilService,
		private dataService: DataResolverService,
		private cdRef: ChangeDetectorRef,
		private router: Router
	) { }

	ngOnChanges(): void {
		// Get navigation data to build breadcrumb with
		this.dataService.getNavigationData().then(nav => {
			this.navigation = nav;
			this.buildBreadcrumb();
		});
	}

	ngOnDestroy(): void {
		if (this.subscription) { this.subscription.unsubscribe(); }
	}

	/** Builds breadcrumbs from navigation data */
	private buildBreadcrumb() {
		const breadcrumbList = [];
		
		let url = this.router.routerState.snapshot.url.split('?')[0].split('#')[0].split('/');
		
		// Add root to beginning of breadcrumb
		const home: Crumb = {
			title: this.util.extract(this.navigation, 'TitleOverride') || this.util.extract(this.navigation, 'Title'),
			url: this.util.extract(this.navigation, 'Url'),
			metaData: this.util.extract(this.navigation, 'Metadata')
		};

		let fullUrl = this.util.extract(this.navigation, 'Url');
		breadcrumbList.push(home);

		let navItems = this.util.extract(this.navigation, 'Items');

		let lastSg = url.length - 1;
		
		if (url[lastSg].includes('productid-')) {
			url = url.slice(0, url.length - 1);
		}

		if (url[lastSg] === 'index' || url[lastSg] === 'index.html') { // Ignore index if it's the last part of the URL
			lastSg = url.length - 2;
		}

		// Build breadcrumb
		url.forEach((sg, index, urlArray) => {
			for (const i in navItems) {
				if (navItems && navItems[i].Url.toLowerCase() === (fullUrl + '/' + sg).toLowerCase()) {
					const crumb: Crumb = {
						title: this.util.extract(navItems[i], 'TitleOverride') || this.util.extract(navItems[i], 'Title'),
						url: this.util.extract(navItems[i], 'Url'),
						metaData: this.util.extract(navItems[i], 'Metadata')
					};
					breadcrumbList.push(crumb);
					fullUrl = fullUrl + '/' + sg;
					
					// Only show breadcrumbs if current page allows it
					this.showBreadcrumbs = !(index === lastSg && navItems[i].ShowBreadcrumbs && navItems[i].ShowBreadcrumbs.toLowerCase() === 'no');
					
						// Set navItems to next level of Items
					navItems = this.util.extract(navItems[i], 'Items');

					break;
				}
			}
		});

		this.breadcrumbs = breadcrumbList;
		this.cdRef.detectChanges();
	}

	/** Checks if the given breadcrumb is clickable */
	public isClickable(crumb): boolean {
		// Only return false if it is explicitly set to no link, if it's set to clickable or missing return true
		const behaviourItem = this.util.extract(crumb.metaData, 'behaviourMegaMenuItem');
		return behaviourItem !== 'No link';
	}
}
<div class="container" *ngIf="breadcrumbs.length > 0 && showBreadcrumbs">
    <nav aria-label="breadcrumb">
        <ol class="breadcrumb" [ngClass]="themeColor">
            <li class="breadcrumb-item" *ngFor="let crumb of breadcrumbs; let last=last" [attr.aria-current]="last ? 'page': null">
                <a class="crumb" *ngIf="isClickable(crumb) && !last" [routerLink]="crumb.url">{{crumb.title}}</a>
                <span class="crumb" [ngClass]="{'active': last}" *ngIf="!isClickable(crumb) || last">{{crumb.title}}</span>
            </li>
        </ol>
    </nav>
</div>

./breadcrumb.component.scss

@import "src/app/styles/helpers";
@import "~bootstrap/scss/breadcrumb";

.breadcrumb {
    background-color: inherit;
    display: none;
    margin-bottom: 0;

    @include media-breakpoint-up(lg) {
        display: flex;
    }

    &-item + &-item {
        padding-left: calc-rem(12);

        &:before {
            color: $green-smoke;
            padding-right: calc-rem(12);
        }
    }

    &-item {
        .crumb {
            @include font-scale(14, medium);
        }
    }

    // Light theme
    &.light &-item {
        .crumb {
            color: $light-blue;

            &.active {
                color: $white;
            }

        }
    }

    // Dark theme
    &.dark &-item {
        .crumb {
            color: $dark-blue;

            &.active {
                color: $cool-grey;
            }
        }
    }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""