Skip to content
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
3 changes: 2 additions & 1 deletion projects/ppwcode/ng-wireframe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ The following CSS variables are available for theming. Just add them to the `bod
### Wireframe

The wireframe places an application layout with responsive left navigation and a toolbar on your web page.
You can hide the wireframe by adding a flag in the route configuration - In data add the `'showWireframe: false'` flag - If this flag is not added it will by default be true and show the wireframe
You can hide the wireframe entirely by adding the `showWireframe: false` flag to the route data. If this flag is not added, the wireframe is shown by default.
You can hide the toolbar while keeping the wireframe visible by adding the `showToolbar: false` flag to the route data. If this flag is not added, the toolbar is shown by default.

#### Parameters

Expand Down
18 changes: 18 additions & 0 deletions projects/ppwcode/ng-wireframe/src/lib/model/wireframe-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { InjectionToken, ValueProvider } from '@angular/core'

export interface WireframeOptions {
showToolbar?: boolean
}

const defaultWireframeOptions: WireframeOptions = {
showToolbar: true
}

export const WIREFRAME_OPTIONS = new InjectionToken<WireframeOptions>('WireframeOptions', {
factory: () => defaultWireframeOptions
})

export const provideWireframeOptions = (options?: WireframeOptions): ValueProvider => ({
provide: WIREFRAME_OPTIONS,
useValue: options ? options : defaultWireframeOptions
})
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"
>
<div class="ppw-page-container">
@if (showWireframe()) {
@if (showWireframe() && showToolbar()) {
<ppw-toolbar
(toggleSidebar)="toggleSidebar()"
[isSidenavOpen]="sidebarIsOpen"
Expand All @@ -56,7 +56,7 @@
</ng-container>
</ppw-toolbar>
}
@if (showBreadcrumb()) {
@if (resolvedShowBreadcrumb()) {
<ppw-breadcrumb>
<ng-container ppw-breadcrumb-home>
<ng-content select="[ppw-breadcrumb-home]">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { provideRouter, Route, Router } from '@angular/router'
import { provideTranslateService } from '@ngx-translate/core'
import { provideBreadcrumbOptions } from '@ppwcode/ng-router'
import { provideWireframeOptions, WireframeOptions } from '../model/wireframe-options'
import { WireframeComponent } from './wireframe.component'

@Component({
selector: 'ppw-visible-route',
template: '',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush
})
class VisibleRouteComponent {}

@Component({
selector: 'ppw-hidden-toolbar-route',
template: '',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush
})
class HiddenToolbarRouteComponent {}

@Component({
selector: 'ppw-toolbar-override-route',
template: '',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush
})
class ToolbarOverrideRouteComponent {}

@Component({
selector: 'ppw-hidden-breadcrumb-route',
template: '',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush
})
class HiddenBreadcrumbRouteComponent {}

const routes: Route[] = [
{
path: 'visible',
component: VisibleRouteComponent,
title: 'Visible page'
},
{
path: 'hidden-toolbar',
component: HiddenToolbarRouteComponent,
title: 'Hidden toolbar page',
data: {
showToolbar: false,
showBreadcrumb: true
}
},
{
path: 'toolbar-override',
component: ToolbarOverrideRouteComponent,
title: 'Toolbar override page',
data: {
showToolbar: true
}
},
{
path: 'hidden-breadcrumb',
component: HiddenBreadcrumbRouteComponent,
title: 'Hidden breadcrumb page',
data: {
showBreadcrumb: false
}
}
]

describe('WireframeComponent', () => {
let component: WireframeComponent
let fixture: ComponentFixture<WireframeComponent>
let router: Router

const setup = async (wireframeOptions?: WireframeOptions): Promise<void> => {
TestBed.resetTestingModule()

await TestBed.configureTestingModule({
imports: [WireframeComponent],
providers: [
provideTranslateService({}),
provideBreadcrumbOptions(),
provideRouter(routes),
...(wireframeOptions ? [provideWireframeOptions(wireframeOptions)] : [])
]
}).compileComponents()

router = TestBed.inject(Router)
fixture = TestBed.createComponent(WireframeComponent)
component = fixture.componentInstance
fixture.componentRef.setInput('showBreadcrumb', true)
}

it('should show the toolbar by default', async () => {
await setup()
await router.navigateByUrl('/visible')
fixture.detectChanges()

expect(component.showToolbar()).toBe(true)
expect(fixture.nativeElement.querySelector('ppw-toolbar')).toBeTruthy()
})

it('should hide the toolbar when the activated route data disables it', async () => {
await setup()
await router.navigateByUrl('/hidden-toolbar')
fixture.detectChanges()

expect(component.showToolbar()).toBe(false)
expect(fixture.nativeElement.querySelector('ppw-toolbar')).toBeFalsy()
})

it('should hide the toolbar when wireframe options disable it by default', async () => {
await setup({ showToolbar: false })
await router.navigateByUrl('/visible')
fixture.detectChanges()

expect(component.showToolbar()).toBe(false)
expect(fixture.nativeElement.querySelector('ppw-toolbar')).toBeFalsy()
})

it('should show the toolbar when route data overrides the global default', async () => {
await setup({ showToolbar: false })
await router.navigateByUrl('/toolbar-override')
fixture.detectChanges()

expect(component.showToolbar()).toBe(true)
expect(fixture.nativeElement.querySelector('ppw-toolbar')).toBeTruthy()
})

it('should keep the breadcrumb visible when the toolbar is hidden by route data', async () => {
await setup()
await router.navigateByUrl('/hidden-toolbar')
fixture.detectChanges()

expect(component.showToolbar()).toBe(false)
expect(component.resolvedShowBreadcrumb()).toBe(true)
expect(fixture.nativeElement.querySelector('ppw-toolbar')).toBeFalsy()
expect(fixture.nativeElement.querySelector('ppw-breadcrumb')).toBeTruthy()
})

it('should let route data hide the breadcrumb even when the input enables it', async () => {
await setup()
await router.navigateByUrl('/hidden-breadcrumb')
fixture.detectChanges()

expect(component.resolvedShowBreadcrumb()).toBe(false)
expect(fixture.nativeElement.querySelector('ppw-breadcrumb')).toBeFalsy()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { BreadcrumbComponent } from '@ppwcode/ng-router'
import { filter } from 'rxjs'
import { LeftSidenavComponent } from '../left-sidenav/left-sidenav.component'
import { SidebarOptions } from '../model/sidebar-options'
import { WIREFRAME_OPTIONS, WireframeOptions } from '../model/wireframe-options'
import { NavigationItem } from '../navigation-item/navigation-item.model'
import { ToolbarComponent } from '../toolbar/toolbar.component'

Expand All @@ -40,6 +41,7 @@ import { ToolbarComponent } from '../toolbar/toolbar.component'
export class WireframeComponent {
#observer: BreakpointObserver = inject(BreakpointObserver)
#router: Router = inject(Router)
#wireframeOptions: WireframeOptions = inject(WIREFRAME_OPTIONS)

#breakpointChange = toSignal(
this.#observer.observe([Breakpoints.XSmall, Breakpoints.Small]).pipe(takeUntilDestroyed())
Expand Down Expand Up @@ -84,15 +86,15 @@ export class WireframeComponent {

// Computed properties
public showWireframe: Signal<boolean> = computed(() => {
// This acts as a trigger for the computed property.
this.#navigationEnd()
return this.#getCurrentRouteSnapshot().data['showWireframe'] ?? true
})

let child: ActivatedRouteSnapshot = this.#router.routerState.snapshot.root
while (child.firstChild) {
child = child.firstChild
}
public showToolbar: Signal<boolean> = computed(() => {
return this.#getCurrentRouteSnapshot().data['showToolbar'] ?? this.#wireframeOptions.showToolbar ?? true
})

return child.data['showWireframe'] ?? true
public resolvedShowBreadcrumb: Signal<boolean> = computed(() => {
return this.showWireframe() && (this.#getCurrentRouteSnapshot().data['showBreadcrumb'] ?? this.showBreadcrumb())
})

public sidenavMode: Signal<'over' | 'side'> = computed(() => {
Expand Down Expand Up @@ -136,4 +138,16 @@ export class WireframeComponent {
return this.#observer.isMatched(breakpoints)
})
}

#getCurrentRouteSnapshot(): ActivatedRouteSnapshot {
// This acts as a trigger for the computed properties that depend on the active route snapshot.
this.#navigationEnd()

let child: ActivatedRouteSnapshot = this.#router.routerState.snapshot.root
while (child.firstChild) {
child = child.firstChild
}

return child
}
}
1 change: 1 addition & 0 deletions projects/ppwcode/ng-wireframe/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from './lib/left-sidenav/left-sidenav.component'
export * from './lib/toolbar/toolbar.component'
export * from './lib/wireframe/wireframe.component'
export * from './lib/model/sidebar-options'
export * from './lib/model/wireframe-options'
5 changes: 4 additions & 1 deletion src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export const routes: Routes = [
{
path: getRouteSegment(ROUTE_MAP.globalErrorHandler),
component: GlobalErrorHandlerComponent,
title: 'navigation.global_error_handler'
title: 'navigation.global_error_handler',
data: {
showToolbar: false
}
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
should never occur on a production environment, but it is useful for development and testing.
"
></ppw-message-bar>
<ppw-message-bar
[severity]="Severity.info"
message="
This demo route sets showToolbar to false in its route data, so the ppw-wireframe toolbar is hidden here while the breadcrumb can still remain visible.
"
></ppw-message-bar>
<h2>Usage</h2>
<p>Add the following snippet to your app module providers.</p>
<pre>
Expand Down
4 changes: 3 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { provideGlobalErrorHandler } from '@ppwcode/ng-common'
import { PPW_TABLE_DEFAULT_OPTIONS } from '@ppwcode/ng-common-components'
import { provideBreadcrumbOptions, providePaginationOptions, TranslatedPageTitleStrategy } from '@ppwcode/ng-router'
import { provideWireframeOptions } from '@ppwcode/ng-wireframe'
import { AppComponent } from './app/app.component'
import { routes } from './app/app.routes'
import { EmptyAsyncResultComponent } from './app/table/empty-async-result.component'
Expand Down Expand Up @@ -78,7 +79,8 @@ bootstrapApplication(AppComponent, {
suffix: '.json'
})
}),
provideBreadcrumbOptions()
provideBreadcrumbOptions(),
provideWireframeOptions()
]
}).catch((err) => console.error(err))

Expand Down
Loading