src/lib/sidenav/sidenav.component.ts
| changeDetection | ChangeDetectionStrategy.OnPush |
| selector | rxap-sidenav |
| imports |
MatIcon
MatIconButton
MatSidenav
MatSidenavContainer
MatSidenavContent
NavigationComponent
NgIf
NgClass
NgStyle
MatDivider
NgTemplateOutlet
|
| styleUrls | ./sidenav.component.scss |
| templateUrl | ./sidenav.component.html |
Properties |
|
Methods |
|
| Async closeSidenav |
closeSidenav()
|
|
Defined in src/lib/sidenav/sidenav.component.ts:86
|
|
Returns :
any
|
| onOpenedChanged | ||||||
onOpenedChanged(opened: boolean)
|
||||||
|
Defined in src/lib/sidenav/sidenav.component.ts:75
|
||||||
|
To ensure the open state is in sync with the component. If the sidenav is closed, e.g. clicking outside the sidenav, it is required to manually update the state in the LayoutService.
Parameters :
Returns :
void
|
| Async openSidenav |
openSidenav()
|
|
Defined in src/lib/sidenav/sidenav.component.ts:81
|
|
Returns :
any
|
| togglePinned |
togglePinned()
|
|
Defined in src/lib/sidenav/sidenav.component.ts:66
|
|
Returns :
void
|
| Public Readonly collapsable |
Type : Signal<boolean>
|
Default value : computed(() => this.layoutService.collapsable())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:61
|
| Public Readonly collapsed |
Type : Signal<boolean>
|
Default value : computed(() => this.layoutService.collapsed())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:60
|
| Public Readonly fixedBottomGap |
Type : Signal<number>
|
Default value : computed(() => this.layoutService.fixedBottomGap())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:56
|
| Public Readonly fixedInViewport |
Type : Signal<boolean>
|
Default value : computed(() => this.layoutService.fixedInViewport())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:58
|
| Public Readonly fixedTopGap |
Type : Signal<number>
|
Default value : computed(() => this.layoutService.fixedTopGap())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:57
|
| Protected Readonly layoutService |
Default value : inject(LayoutService)
|
|
Defined in src/lib/sidenav/sidenav.component.ts:51
|
| Public Readonly opened |
Type : Signal<boolean>
|
Default value : computed(() => this.layoutService.opened())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:62
|
| Public Readonly pinned |
Type : Signal<boolean>
|
Default value : computed(() => this.layoutService.pinned())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:59
|
| Protected Readonly sidenav |
Default value : viewChild(MatSidenav)
|
|
Defined in src/lib/sidenav/sidenav.component.ts:53
|
| Public Readonly sidenavFooterDirective |
Default value : contentChild(SidenavFooterDirective)
|
|
Defined in src/lib/sidenav/sidenav.component.ts:63
|
| Public Readonly sidenavHeaderDirective |
Default value : contentChild(SidenavHeaderDirective)
|
|
Defined in src/lib/sidenav/sidenav.component.ts:64
|
| Public Readonly sidenavMode |
Type : Signal<MatDrawerMode>
|
Default value : computed(() => this.layoutService.mode())
|
|
Defined in src/lib/sidenav/sidenav.component.ts:55
|
import {
NgClass,
NgIf,
NgStyle,
NgTemplateOutlet,
} from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
computed,
contentChild,
inject,
Signal,
viewChild,
} from '@angular/core';
import { MatIconButton } from '@angular/material/button';
import { MatDivider } from '@angular/material/divider';
import { MatIcon } from '@angular/material/icon';
import {
MatDrawerMode,
MatSidenav,
MatSidenavContainer,
MatSidenavContent,
} from '@angular/material/sidenav';
import { LayoutService } from '../layout.service';
import { NavigationComponent } from '../navigation/navigation.component';
import { SidenavFooterDirective } from './sidenav-footer.directive';
import { SidenavHeaderDirective } from './sidenav-header.directive';
@Component({
selector: 'rxap-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
MatIcon,
MatIconButton,
MatSidenav,
MatSidenavContainer,
MatSidenavContent,
NavigationComponent,
NgIf,
NgClass,
NgStyle,
MatDivider,
NgTemplateOutlet,
],
})
export class SidenavComponent {
protected readonly layoutService = inject(LayoutService);
protected readonly sidenav = viewChild(MatSidenav);
public readonly sidenavMode: Signal<MatDrawerMode> = computed(() => this.layoutService.mode());
public readonly fixedBottomGap: Signal<number> = computed(() => this.layoutService.fixedBottomGap());
public readonly fixedTopGap: Signal<number> = computed(() => this.layoutService.fixedTopGap());
public readonly fixedInViewport: Signal<boolean> = computed(() => this.layoutService.fixedInViewport());
public readonly pinned: Signal<boolean> = computed(() => this.layoutService.pinned());
public readonly collapsed: Signal<boolean> = computed(() => this.layoutService.collapsed());
public readonly collapsable: Signal<boolean> = computed(() => this.layoutService.collapsable());
public readonly opened: Signal<boolean> = computed(() => this.layoutService.opened());
public readonly sidenavFooterDirective = contentChild(SidenavFooterDirective);
public readonly sidenavHeaderDirective = contentChild(SidenavHeaderDirective);
togglePinned() {
this.layoutService.togglePinned();
}
/**
* To ensure the open state is in sync with the component. If the sidenav is closed, e.g. clicking outside the sidenav,
* it is required to manually update the state in the LayoutService.
* @param opened
*/
onOpenedChanged(opened: boolean) {
if (!opened) {
this.layoutService.closeSidenav();
}
}
async openSidenav() {
await this.sidenav()?.open();
this.layoutService.openSidenav();
}
async closeSidenav() {
await this.sidenav()?.close();
this.layoutService.closeSidenav();
}
}
<mat-sidenav-container [ngStyle]="{
'padding-top.px': fixedTopGap(),
'padding-bottom.px': fixedBottomGap(),
}" class="h-full">
<mat-sidenav
[fixedBottomGap]="fixedBottomGap()"
[fixedInViewport]="fixedInViewport()"
[fixedTopGap]="fixedTopGap()"
[mode]="sidenavMode()"
[ngClass]="{ collapsable: collapsable() }"
[opened]="opened()"
(openedChange)="onOpenedChanged($event)"
>
<div (mouseleave)="collapsable() && !pinned() && closeSidenav()"
class="h-full py-2 flex flex-col items-center gap-y-5 justify-items-stretch">
<div (click)="togglePinned()" *ngIf="collapsable()"
class="pl-2 self-stretch grow-0 flex flex-row justify-between items-center">
<span class="text-lg" i18n>Navigation</span>
<div class="flex flex-row items-center justify-center" style="width: 64px">
<button mat-icon-button>
<mat-icon *ngIf="!pinned()">radio_button_unchecked</mat-icon>
<mat-icon *ngIf="pinned()">radio_button_checked</mat-icon>
</button>
</div>
</div>
@if (sidenavHeaderDirective()?.template; as template) {
<div [ngClass]="{ hidden: collapsed() }" class="header grow-0">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
<mat-divider [ngClass]="{ hidden: collapsed() }" class="grow-0"></mat-divider>
}
<ul
(mouseenter)="collapsable() && !pinned() && openSidenav()"
class="grow self-stretch"
[root]="true"
rxap-navigation
>
</ul>
@if (sidenavFooterDirective()?.template; as template) {
<mat-divider [ngClass]="{ hidden: collapsed() }" class="grow-0"></mat-divider>
<div [ngClass]="{ hidden: collapsed() }" class="footer grow-0">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
}
</div>
</mat-sidenav>
<mat-sidenav-content [ngClass]="{ 'ml-16': collapsable() }" class="p-4">
<ng-content></ng-content>
</mat-sidenav-content>
</mat-sidenav-container>
./sidenav.component.scss
:host {
.collapsable.mat-drawer {
&:not(.mat-drawer-opened) {
transform: translateX(calc(-100% + 64px)) !important;
visibility: visible !important;
box-shadow: inherit !important;
transition-property: transform;
transition-delay: 250ms;
display: flex;
border-right: solid 1px rgba(0, 0, 0, .12);
::ng-deep .mat-drawer-inner-container {
display: block;
}
}
::ng-deep .mat-drawer-inner-container::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera*/
}
}
}