Skip to content

Commit

Permalink
feat: breadcrumb as a function, merge with child breadcrumbs properly (
Browse files Browse the repository at this point in the history
…#45)

feat: breadcrumb as a function, merge with child breadcrumbs without losing context
  • Loading branch information
udayvunnam authored Sep 7, 2020
1 parent 089acd9 commit fee7608
Show file tree
Hide file tree
Showing 13 changed files with 355 additions and 318 deletions.
4 changes: 2 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## PR Checklist

Please check if your PR fulfills the following requirements:
Please check if your PR fulfils the following requirements:

- [ ] The commit message follows the guidelines: https://github.com/scullyio/scully/blob/main/CONTRIBUTING.md#commit
- [ ] The commit message follows [the guidelines](https://github.com/scullyio/scully/blob/main/CONTRIBUTING.md#commit)
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)

Expand Down
41 changes: 28 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ Note: XngBreadcrumb has a peer dependency on `@angular/router`. Include `RouterM
### Custom breadcrumb labels via Angular Route Config

- define 'breadcrumb' within the data property of route.
- a 'breadcrumb' can be defined as a **string** OR **object**.
- a 'breadcrumb' can be defined as a **string** OR **object** OR **function**.
- Use **breadcrumb as a string** if you are just providing breadcrumb text
- Use **breadcrumb as an object** if you are providing additional properties like 'alias', 'skip', 'info', 'disable'. In you define breadcrumb as an object, **label** property denotes breadcrumb text.
- Use **breadcrumb as a function** if you want to alter the auto-generated label as needed.

#### breadcrumb as a string

Expand Down Expand Up @@ -137,6 +138,20 @@ Note: XngBreadcrumb has a peer dependency on `@angular/router`. Include `RouterM
}
```

#### breadcrumb as a function

```javascript
{
path: '/orders',
children: [{
':id',
data: {
breadcrumb: (resolvedId: string) => `Viewing ${resolvedId} now`
}
}]
}
```

### Update labels dynamically

- Breadcrumb label can be updated dynamically using _route path_ or _alias_
Expand Down Expand Up @@ -351,20 +366,20 @@ You can display whatever you want in the place of breadcrumb text by providing a

## API

### Route Config
### App Route Config -> data -> breadcrumb

| property | Description | Type | Default |
| --------------------- | ---------------------------------------------------------------- | --------------------- | ----------- |
| breadcrumb | Breadcrumb data provided in App route config | `string | Breadcrumb` | `undefined` |
| breadcrumb: {alias} | alias name for a route | `string` | `undefined` |
| breadcrumb: {skip} | skip a route from showing in breadcrumbs | `boolean` | `false` |
| breadcrumb: {disable} | disable navigation for a breadcrumb item | `boolean` | `false` |
| breadcrumb: {info} | arbitrary info for a breadcrumb. | `string | object` | `undefined` |
| breadcrumb: {label} | same as breadcrumb. Use label if breadcrumb is defined as object | `string` | `undefined` |
| property | Description | Type | Default |
| --------------------- | ---------------------------------------------------------------- | -------------------------------- | ----------- |
| breadcrumb | Breadcrumb data provided in App route config | `string | Breadcrumb | Function` | `undefined` |
| breadcrumb: {alias} | alias name for a route | `string` | `undefined` |
| breadcrumb: {skip} | skip a route from showing in breadcrumbs | `boolean` | `false` |
| breadcrumb: {disable} | disable navigation for a breadcrumb item | `boolean` | `false` |
| breadcrumb: {info} | arbitrary info for a breadcrumb. | `string | object` | `undefined` |
| breadcrumb: {label} | same as breadcrumb. Use label if breadcrumb is defined as object | `string` | `undefined` |

### xng-breadcrumb
### xng-breadcrumb component

| property | Description | Type | Default |
| Input | Description | Type | Default |
| ------------------- | --------------------------------------------------------- | ---------------------------- | ------- |
| separator | input: separator between breadcrumbs | `string | TemplateRef<void>` | `/` |
| autoGenerate | input:whether to auto generate breadcrumb labels | `boolean` | `true` |
Expand All @@ -390,7 +405,7 @@ You can display whatever you want in the place of breadcrumb text by providing a
// defining breadcrumb on Component Route
{
path: ':userId',
data: { breadcrumb: 'Declaraed on Parent Component' },
data: { breadcrumb: 'Declared on Parent Component' },
children: [
{ path: '', component: ShowUserComponent }
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getDefaultBreadcrumbs } from '../support/app.po';
import { resolve } from 'cypress/types/bluebird';

describe('breadcrumb-demo', () => {
// beforeEach(() => cy.visit('/'));
Expand All @@ -8,7 +9,7 @@ describe('breadcrumb-demo', () => {
getDefaultBreadcrumbs().contains('my home');
});

it('should have valid path and breadcrumbs for Metors via navbar', () => {
it('should have valid path and breadcrumbs for Mentors via navbar', () => {
cy.get('.navbar').contains('Mentors').click();
cy.location().should((loc) => {
expect(loc.pathname).to.eq('/mentor');
Expand All @@ -19,7 +20,7 @@ describe('breadcrumb-demo', () => {
getDefaultBreadcrumbs().contains('Enabler');
});

it('should have valid path and breadcrumbs for Mentor Details', () => {
it('should have valid path and breadcrumbs for Mentor Details', () => {
cy.get('bd-mentor-list .mat-card-avatar').eq(0).click();
cy.location().should((loc) => {
mentorDetailsPath = loc.pathname;
Expand All @@ -34,7 +35,7 @@ describe('breadcrumb-demo', () => {
});
});

it('should have valid path and breadcrumbs for Mentor Edit', () => {
it('should have valid path and breadcrumbs for Mentor Edit', () => {
cy.get('bd-mentor-details').contains('Edit').click();
cy.location().should((loc) => {
expect(loc.search).to.eq('?type=edit');
Expand All @@ -45,12 +46,39 @@ describe('breadcrumb-demo', () => {
getDefaultBreadcrumbs().contains('Edit').should('not.exist');
});

it('should have valid path for navigating via breadcrumb', () => {
it('should have valid path while navigating via breadcrumb', () => {
getDefaultBreadcrumbs().contains('Enabler').click();
cy.location().should((loc) => {
// expect(loc.hash).to.eq('#/users/123/edit')
expect(loc.pathname).to.eq('/mentor');
expect(loc.search).to.eq('?viaNav=true&type=list');
});
});

it('Should merge parent module/component data with child module/component', () => {
cy.visit('/');
cy.get('.navbar-header').contains('Mentees').click();
cy.get('bd-mentee-list .mat-card-avatar').eq(0).click();
getDefaultBreadcrumbs().contains('Mentee (Root)').should('not.exist'); // defined on parent module
getDefaultBreadcrumbs().contains('student'); // Defined on child module
cy.get('#default .xng-breadcrumb-link.xng-breadcrumb-link-disabled').should(
'exist'
); // defined on grand child component
});

it('Should have customized breadcrumb working via *xngBreadcrumbItem directive', () => {
cy.get('#titleCase').contains('Student'); // title case
cy.get('#titleCase').contains('>>'); // custom seperator
});

it('Should have invoked breadcrumb as a function with resolved param', () => {
cy.visit('/');
cy.get('.navbar-header').contains('Mentees').click();
cy.get('bd-mentee-list .mat-card-avatar').eq(0).click();

cy.location('pathname').then((pathname) => {
const resolvedId = pathname.split('').pop();
getDefaultBreadcrumbs().contains(`Viewing ${resolvedId} now`);
});
});
});
21 changes: 12 additions & 9 deletions apps/breadcrumb-demo-e2e/src/integration/query-params.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@ import { getDefaultBreadcrumbs } from '../support/app.po';
describe('breadcrumb-demo', () => {
it('should preserve query params by default', () => {
cy.visit('/');
cy.get('.navbar-header').contains('Mentees').click();
cy.get('.navbar-header').contains('Mentors').click();
cy.location().should((loc) => {
expect(loc.search).to.eq('?viaNav=true');
expect(loc.search).to.eq('?viaNav=true&type=list');
});
cy.get('bd-mentee-list .mat-card-avatar').eq(0).click();
getDefaultBreadcrumbs().contains('mentee').click();
cy.get('bd-mentor-list .mat-card-avatar').eq(0).click();
cy.location().should((loc) => {
expect(loc.search).to.eq('?viaNav=true');
expect(loc.search).to.eq('?type=details');
});
getDefaultBreadcrumbs().contains('Enabler').click();
cy.location().should((loc) => {
expect(loc.search).to.eq('?viaNav=true&type=list');
});
});

it('should not preserve query params for disabled queryparams', () => {
cy.visit('/');
cy.get('.navbar-header').contains('Mentees').click();
cy.get('.navbar-header').contains('Mentors').click();
cy.location().should((loc) => {
expect(loc.search).to.eq('?viaNav=true');
expect(loc.search).to.eq('?viaNav=true&type=list');
});
cy.get('bd-mentee-list .mat-card-avatar').eq(0).click();
cy.get('#advancedTemplate1').contains('Mentee').click();
cy.get('bd-mentor-list .mat-card-avatar').eq(0).click();
cy.get('#advancedTemplate1').contains('Enabler').click();
cy.location().should((loc) => {
expect(loc.search).to.eq('');
});
Expand Down
1 change: 1 addition & 0 deletions apps/breadcrumb-demo/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const appRoutes: Routes = [
data: {
breadcrumb: {
info: 'person_outline',
label: 'Mentee (Root)',
},
},
},
Expand Down
12 changes: 10 additions & 2 deletions apps/breadcrumb-demo/src/app/mentee/mentee-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { MenteeEditComponent } from './mentee-edit/mentee-edit.component';
const routes: Routes = [
{
path: '',
data: {
breadcrumb: 'student',
},
component: MenteeComponent,
children: [
{
Expand All @@ -19,8 +22,8 @@ const routes: Routes = [
{
path: ':id',
data: {
breadcrumb: {
alias: 'menteeName',
breadcrumb: (id) => {
return `Viewing ${id} now`;
},
},
children: [
Expand All @@ -42,6 +45,11 @@ const routes: Routes = [
{
path: '',
component: MenteeListComponent,
data: {
breadcrumb: {
disable: true,
},
},
},
],
},
Expand Down
2 changes: 1 addition & 1 deletion libs/xng-breadcrumb/src/lib/breadcrumb-item.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Directive } from '@angular/core';
/**
* This directive is used to customize the breadcrumb label behavior
* *xngBreadcrumbItem directive can be used in the child element of xng-breadcrumb
* Usage: refer to demo app.component.html
* Usage: refer to the demo - app.component.html
*/
@Directive({
selector: '[xngBreadcrumbItem]',
Expand Down
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 @@ -11,7 +11,7 @@ import {
import { Observable, Subscription } from 'rxjs';
import { BreadcrumbItemDirective } from './breadcrumb-item.directive';
import { BreadcrumbService } from './breadcrumb.service';
import { Breadcrumb } from './breadcrumb';
import { Breadcrumb } from './types/breadcrumb';

@Component({
selector: 'xng-breadcrumb',
Expand Down
Loading

0 comments on commit fee7608

Please sign in to comment.