Skip to content

Instantly share code, notes, and snippets.

@bryandh
Last active May 16, 2018 10:02
Show Gist options
  • Save bryandh/c9baf34fb39765b19b4b3c2bed57ce0e to your computer and use it in GitHub Desktop.
Save bryandh/c9baf34fb39765b19b4b3c2bed57ce0e to your computer and use it in GitHub Desktop.
Aurelia Breadcrumbs

Aurelia Breadcrumbs

Gathers the navigation instructions and displays the taken routes to get to the current route.

How it works

Requires your routing to be set up with child routing to achieve multiple layers of routing. Refreshes on Aurelia's router:navigation:complete event.

<template class="breadcrumbs">
<require from="./breadcrumbs.css"></require>
<require from="../../converters/GenerateRouteUrlValueConverter"></require>
<ol class="breadcrumb">
<li repeat.for="navInstruction of navInstructions" class="breadcrumb-item" class.bind="$last ? 'active' : ''">
<template if.bind="!$last">
<a href="${navInstruction | generateRouteUrl}" click.delegate="navigateToRoute(navInstruction)">
${navInstruction.config.navModel.title}
</a>
</template>
<template if.bind="$last">
${navInstruction.config.navModel.title}
</template>
</li>
</ol>
</template>
@import '../../../assets/styles/globals';
.breadcrumbs {
margin: .25rem .5rem;
align-self: flex-end;
min-width: 0;
direction: rtl;
-ms-overflow-style: none;
overflow-x: scroll;
&::-webkit-scrollbar {
display: none;
}
.breadcrumb {
float: right;
direction: ltr;
background-color: transparent;
margin-bottom: 0;
padding: 0;
flex-wrap: nowrap;
.breadcrumb-item {
white-space: nowrap;
a,
& {
color: $dark-gray;
}
a {
&:hover {
color: $orange;
}
}
&.active {
color: $orange;
}
+::before {
content: '|';
padding-right: 0;
padding-left: .25rem;
}
}
}
}
import { autoinject } from 'aurelia-dependency-injection';
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
import { NavigationInstruction, Router } from 'aurelia-router';
@autoinject
export class Breadcrumbs {
public navInstructions: NavigationInstruction[] = [];
private onNavigationComplete: Subscription;
constructor(
private router: Router,
private eventAggregator: EventAggregator
) {
this.onNavigationComplete = this.eventAggregator.subscribe('router:navigation:complete', () => this.refresh());
}
private refresh(): void {
const parentInstructions = this.getParentInstructions(this.router.currentInstruction);
this.navInstructions = parentInstructions
.slice(0, parentInstructions.length - 1)
.concat(this.router.currentInstruction.getAllInstructions())
.filter((instruction) => instruction.config.settings.breadcrumb && instruction.config.title);
}
private navigateToRoute(instruction: NavigationInstruction): void {
const params = Object.assign(instruction.params);
delete params.childRoute;
instruction.router.navigateToRoute(instruction.config.name, instruction.params);
}
private getParentInstructions(instruction: NavigationInstruction): NavigationInstruction[] {
return instruction.parentInstruction
? this.getParentInstructions(instruction.parentInstruction).concat([instruction])
: [instruction];
}
private detached(): void {
if (this.onNavigationComplete)
this.onNavigationComplete.dispose();
}
}
import { NavigationInstruction } from 'aurelia-router';
export class GenerateRouteUrlValueConverter {
/**
* Generates a route URL for given navigation instruction.
* @param instruction The instruction to generate a route url for.
* @param absolute Whether the route url should be absolute (https://absolute.path/route/path).
* If false, the URL will be relative (/relative/path).
*/
private toView(instruction: NavigationInstruction, absolute: boolean = false): string {
const params = Object.assign(instruction.params);
// Remove the childRoute parameter, placed there by the router, from the params object as we don't need it here
delete params.childRoute;
// Generate the route URL for the given instruction
return instruction.router.generate(instruction.config.name, params, { absolute });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment