I'm using Angular 9 and I've used the boiler plate sidenav Angular Material template. I'm forcing the sidenav to be open all the time when in larger size screens and a hamburger icon when in smaller sizes.
During the login process, when a user isn't authenticated, the sidenav and hamburger icon are hidden with an *ngIf. I also use a template ref variable #drawer on the sidenav container to be referenced by the hamburger icon (click)="drawer.toggle()"
The problem I believe is because I'm not showing these items before a login happens, the template ref variable never gets set at the outset of the component creation. So, when I try to use the hamburger icon to toggle the sidenav I get a don't understand toggle of undefined error.
My login component is being shown in a router outlet so it has to stay in this config. Ideally I'd show a login component first, then go to the app when a user is logged in, but I'm not sure how to do that. Looking for a little guidance on this issue if anyone can help.
Thanks so much
---- NAVIGATION COMPONENT ----
<mat-sidenav-container class="sidenav-container">
<mat-sidenav *ngIf="securityObject.isAuthenticated" #drawer class="sidenav" fixedInViewport="true"
[attr.role]="isHandset ? 'dialog' : 'navigation'" [mode]="(isHandset | async)!.matches ? 'over' : 'side'"
[opened]="!(isHandset | async)!.matches">
<mat-toolbar color="primary">Menu</mat-toolbar>
<!-- SIDEBAR NAVIGATION CONTENT -->
<mat-nav-list>
<a mat-list-item routerLink="/users" routerLinkActive="active">
<mat-icon matListIcon>people</mat-icon>Users
</a>
<a mat-list-item routerLink="/clients" routerLinkActive="active">
<mat-icon matListIcon>business</mat-icon>Clients
</a>
<a mat-list-item routerLink="/documents" routerLinkActive="active">
<mat-icon matListIcon>folder</mat-icon>Documents
</a>
<a mat-list-item routerLink="/projects" routerLinkActive="active">
<mat-icon matListIcon>apps</mat-icon>Projects
</a>
<a mat-list-item routerLink="/facility" routerLinkActive="active">
<mat-icon matListIcon>storefront</mat-icon>Facility
</a>
<a mat-list-item routerLink="/tools" routerLinkActive="active">
<mat-icon matListIcon>build</mat-icon>Tools
</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<ng-container *ngIf="securityObject.isAuthenticated">
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()"
*ngIf="(isHandset | async)!.matches">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
</ng-container>
<span>WWP&S Portal</span>
<span class="example-fill-remaining-space"></span>
<span><a routerLink="/logout" (click)="logout()" *ngIf="securityObject.isAuthenticated">
{{ this.securityService.securityObject.username }}</a></span>
</mat-toolbar>
<ng-content></ng-content>
</mat-sidenav-content>
</mat-sidenav-container>
--- NAVIGATION TS FILE ---
import { Component, OnInit, ViewChild } from "@angular/core";
import { Observable } from "rxjs";
import {
BreakpointState,
BreakpointObserver,
Breakpoints,
} from "@angular/cdk/layout";
import { SecurityService } from "../../services/security.service";
import { UserAuth } from "../../models/user-auth";
@Component({
selector: "app-navigation",
templateUrl: "./navigation.component.html",
styleUrls: ["./navigation.component.css"],
})
export class NavigationComponent implements OnInit {
drawer;
securityObject: UserAuth = null;
isHandset: Observable<BreakpointState> = this.breakpointObserver.observe(
Breakpoints.Handset
);
constructor(
private breakpointObserver: BreakpointObserver,
public securityService: SecurityService
) {}
ngOnInit() {
this.securityObject = this.securityService.securityObject;
}
logout(): void {
this.securityService.logout();
}
}