Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: xng-breadcrumb inside ngIf needs a special check since router events are already finished #97

Merged
merged 3 commits into from
Nov 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

- ✅ **Disable breadcrumb**: Disable specific routes so that navigation is disbaled to intermediate routes.

- ✅ **Customization**: Customize breadcrumb template to show **icons as label prefix**, **use pipes on text**, **add i18n**, etc.
- ✅ **Customization**: Customize breadcrumb template to show **icons as label prefix**, **use pipes on text**, **add i18n with ngx-translate**, etc.

- ✅ **Styling**: **Separator** and **Styles** can be customized with ease.

Expand Down
4 changes: 4 additions & 0 deletions apps/simple-demo-e2e/src/integration/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
describe('simple-demo', () => {
it('should contain breadcrumbs for books', () => {
cy.visit('/');
// initially within ngIf and not shown
cy.get('xng-breadcrumb').should('not.exist');
cy.get('button').contains('Toggle Breadcrumb Visibility').click();
cy.get('xng-breadcrumb').contains('Dashboard');

// shouldn't have default seperator if Home breadcrumb is not defined
cy.get('.xng-breadcrumb-list').contains('/').should('not.exist');
cy.get('a').contains('Order Details').click();
Expand Down
39 changes: 8 additions & 31 deletions apps/simple-demo/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,35 +1,12 @@
<h2>xng-breadcrumb</h2>
<h2>Angular version {{ name }}</h2>

<xng-breadcrumb></xng-breadcrumb>
<div *ngIf="showBreadcrumbs">
<xng-breadcrumb></xng-breadcrumb>
</div>

<ul>
<li>
<a href="/company"> Company list </a>
<ul>
<li>
<a href="/company/1"> Company </a>
<ul></ul>
</li>
<li>
<a href="/company/1/order"> Order list </a>
<ul>
<li>
<a href="/company/1/order/2"> Order Details </a>
<ul>
<li>
<a href="/company/1/order/2/items"> Order Items </a>
</li>
<li>
<a href="/company/1/order/2/payment"> Order Payment Info </a>
</li>
<li>
<a href="/company/1/order/2/delivery"> Order Delivery Info </a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<router-outlet></router-outlet>

<button (click)="toggleBreadcrumbVisibility()">
Toggle Breadcrumb Visibility
</button>
7 changes: 7 additions & 0 deletions apps/simple-demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ import { Router } from '@angular/router';
styleUrls: ['./app.component.css'],
})
export class AppComponent {
showBreadcrumbs = false;

constructor(router: Router) {
router.routeReuseStrategy.shouldReuseRoute = () => false;
}

toggleBreadcrumbVisibility() {
this.showBreadcrumbs = !this.showBreadcrumbs;
}

name = 'Angular ' + VERSION.major;
}
9 changes: 4 additions & 5 deletions apps/simple-demo/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { BreadcrumbModule } from '@xng/xng-breadcrumb';
import { BreadcrumbModule, BreadcrumbService } from '@xng/xng-breadcrumb';
import { AppRoutingModule } from './app.routing.module';

import { AppComponent } from './app.component';
import { Page1Component } from './page1.component';
import { Page2Component } from './page2.component';
import { PageComponent } from './page.component';
@NgModule({
declarations: [AppComponent, Page1Component, Page2Component],
declarations: [AppComponent, PageComponent],
imports: [BrowserModule, BreadcrumbModule, AppRoutingModule],
providers: [],
providers: [BreadcrumbService],
bootstrap: [AppComponent],
})
export class AppModule {}
19 changes: 10 additions & 9 deletions apps/simple-demo/src/app/app.routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AppComponent } from './app.component';
import { PageComponent } from './page.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';

export const appRoutes: Routes = [
{
Expand All @@ -10,7 +11,7 @@ export const appRoutes: Routes = [
},
{
path: 'homepage',
component: AppComponent,
component: PageComponent,
data: {
breadcrumb: 'Dashboard',
},
Expand All @@ -19,35 +20,35 @@ export const appRoutes: Routes = [
path: 'company',
data: { breadcrumb: 'Companies' },
children: [
{ path: '', component: AppComponent },
{ path: '', component: PageComponent },
{
path: ':companyId',
data: { breadcrumb: 'Company Name' },
children: [
{ path: '', component: AppComponent },
{ path: '', component: PageComponent },
{
path: 'order',
data: { breadcrumb: 'Orders' },
children: [
{ path: '', component: AppComponent },
{ path: '', component: PageComponent },
{
path: ':orderId',
data: { breadcrumb: 'Order Details' },
children: [
{ path: '', component: AppComponent },
{ path: '', component: PageComponent },
{
path: 'items',
component: AppComponent,
component: PageComponent,
data: { breadcrumb: 'Items' },
},
{
path: 'payment',
component: AppComponent,
component: PageComponent,
data: { breadcrumb: 'Payment Info' },
},
{
path: 'delivery',
component: AppComponent,
component: PageComponent,
data: { breadcrumb: 'Delivery Details' },
},
],
Expand Down
16 changes: 0 additions & 16 deletions apps/simple-demo/src/app/hello.component.ts

This file was deleted.

34 changes: 34 additions & 0 deletions apps/simple-demo/src/app/page.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<ul>
<li>
<a [routerLink]="['/company']"> Company list </a>
<ul>
<li>
<a [routerLink]="['/company/1']"> Company </a>
<ul></ul>
</li>
<li>
<a [routerLink]="['/company/1/order']"> Order list </a>
<ul>
<li>
<a [routerLink]="['/company/1/order/2']"> Order Details </a>
<ul>
<li>
<a [routerLink]="['/company/1/order/2/items']"> Order Items </a>
</li>
<li>
<a [routerLink]="['/company/1/order/2/payment']">
Order Payment Info
</a>
</li>
<li>
<a [routerLink]="['/company/1/order/2/delivery']">
Order Delivery Info
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
7 changes: 7 additions & 0 deletions apps/simple-demo/src/app/page.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Component } from '@angular/core';

@Component({
selector: 'page',
templateUrl: './page.component.html',
})
export class PageComponent {}
7 changes: 0 additions & 7 deletions apps/simple-demo/src/app/page1.component.ts

This file was deleted.

7 changes: 0 additions & 7 deletions apps/simple-demo/src/app/page2.component.ts

This file was deleted.

2 changes: 1 addition & 1 deletion libs/xng-breadcrumb/src/lib/breadcrumb.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
TemplateRef,
ViewEncapsulation,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
import { Observable, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import { BreadcrumbItemDirective } from './breadcrumb-item.directive';
Expand Down
24 changes: 17 additions & 7 deletions libs/xng-breadcrumb/src/lib/breadcrumb.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import {
ActivatedRoute,
ActivatedRouteSnapshot,
Router,
RoutesRecognized,
Expand Down Expand Up @@ -53,30 +54,39 @@ export class BreadcrumbService {
private breadcrumbs = new BehaviorSubject<BreadcrumbDefinition[]>([]);
public breadcrumbs$ = this.breadcrumbs.asObservable();

constructor(private router: Router) {
constructor(private activatedRoute: ActivatedRoute, private router: Router) {
this.detectRouteChanges();
}

/**
* Whenever route changes build breadcrumb list again
*/
private detectRouteChanges() {
// Special case where breadcrumb service & component instantiates after a route is navigated.
// Ex: put breadcrumbs within *ngIf and this.router.events would be empty
if (this.router.navigated) {
this.setupBreadcrumbs(this.activatedRoute.snapshot);
}

this.router.events
.pipe(filter((event) => event instanceof RoutesRecognized))
.subscribe((event) => {
// activatedRoute doesn't carry data when shouldReuseRoute returns false
// use the event data with RoutesRecognized as workaround
if (event instanceof RoutesRecognized) {
console.log(event.state.root.firstChild.data.title);
this.previousBreadcrumbs = this.currentBreadcrumbs;
// breadcrumb label for base OR root path. Usually, this can be set as 'Home'
const rootBreadcrumb = this.getRootBreadcrumb();
this.currentBreadcrumbs = rootBreadcrumb ? [rootBreadcrumb] : [];
this.prepareBreadcrumbList(event.state.root, this.baseHref);
this.setupBreadcrumbs(event.state.root);
}
});
}

private setupBreadcrumbs(activatedRouteSnapshot: ActivatedRouteSnapshot) {
this.previousBreadcrumbs = this.currentBreadcrumbs;
// breadcrumb label for base OR root path. Usually, this can be set as 'Home'
const rootBreadcrumb = this.getRootBreadcrumb();
this.currentBreadcrumbs = rootBreadcrumb ? [rootBreadcrumb] : [];
this.prepareBreadcrumbList(activatedRouteSnapshot, this.baseHref);
}

private getRootBreadcrumb() {
const rootConfig = this.router.config.find((config) => config.path === '');
const rootBreadcrumb = this.extractObject(rootConfig?.data?.breadcrumb);
Expand Down