Search code examples
angulartypescriptangular-material

SideNav Not Opening using Angular Material 17


I'm currently refreshing back my Angular knowledge. Currently, I have two components, mainly header-component (toolbar) and sidenav-component (SideNavigation).

I call the child component (sidenav-component) to my header-component and then subsequently to my app-component.ts. Here are the codes:

header-component.html

<mat-toolbar color="primary" class="toolbar">
  <button (click)="openSideNav()" mat-button color="secondary">
<mat-icon>menu</mat-icon>
</button>
  <img src="../../../assets/logo-pink.png" class="logo" alt="logo">
</mat-toolbar>

<app-side-nav [openedStatus]="openFlag" />

header-component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-header-component',
  templateUrl: './header-component.component.html',
  styleUrl: './header-component.component.scss'
})
export class HeaderComponentComponent implements OnInit {
  openFlag: boolean = false;

  constructor() {}

  ngOnInit() {
    console.info("Header component initialised");
  }

  openSideNav() {
    this.openFlag = !this.openFlag;
    console.info("Open flag", this.openFlag);
  }
}

side-nav-component.html

<mat-sidenav-container autosize>
  <mat-sidenav [opened]="openedStatus" mode="push">
    <mat-nav-list>
      <mat-list-item>
       <button mat-button>
         <mat-icon>home</mat-icon>
         Home
       </button>
      </mat-list-item>

    <mat-list-item>
      <button mat-button>
         <mat-icon>login</mat-icon>
         Login
      </button>
    </mat-list-item>

    <mat-list-item>
      <button mat-button>
         <mat-icon>account</mat-icon>
         Register
      </button>
    </mat-list-item>
  </mat-nav-list>
</mat-sidenav>

side-nav-component.ts

import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';

@Component({
   selector: 'app-side-nav',
   templateUrl: './side-nav.component.html',
   styleUrl: './side-nav.component.scss'
})
export class SideNavComponent implements OnInit, OnChanges {
  @Input() openedStatus: boolean = false;

  constructor() {}

  ngOnChanges(changes: SimpleChanges): void {
    console.info("Open Status", changes['openedStatus'].currentValue);
  }

  ngOnInit(): void {
   console.info("Side Navigation menu component initialised");
  }

}

app-component.html

<main class="main">
  <app-header-component></app-header-component>
</main>

I don't know where am I doing it wrongly but it seems when I click the "button" on the header-component, it's not showing the side nav. Appreciate any help here


Solution

  • When we place the mat-sidenav-container inside a component, the height is lost, so we can either use display: block or use the below CSS, to make it retain the height!

    Please note that we also need to define mat-sidenav-content which contains the content!

      :host {
        display: block;
        height:100vh;
      }
      .full-height {
        height:100% !important;
      }
    

    Working example below!

    PARENT

    import { Component } from '@angular/core';
    import { HeaderComponentComponent } from './header';
    
    /**
     * @title Autosize sidenav
     */
    @Component({
      selector: 'sidenav-autosize-example',
      template: `
      <main class="main">
        <app-header-component></app-header-component>
      </main>
      `,
      standalone: true,
      imports: [HeaderComponentComponent],
    })
    export class SidenavAutosizeExample {
      showFiller = false;
    }
    

    HEADER

    import { Component, OnInit } from '@angular/core';
    import { MatToolbarModule } from '@angular/material/toolbar';
    import { MatIconModule } from '@angular/material/icon';
    import { SideNavComponent } from './sidenav';
    
    @Component({
      selector: 'app-header-component',
      standalone: true,
      imports: [MatToolbarModule, MatIconModule, SideNavComponent],
      template: `
      <mat-toolbar color="primary" class="toolbar">
        <button (click)="openSideNav()" mat-button color="secondary">
          <mat-icon>menu</mat-icon>
        </button>
        <img src="../../../assets/logo-pink.png" class="logo" alt="logo"/>
      </mat-toolbar>
    
      <app-side-nav [openedStatus]="openFlag" />
      `,
    })
    export class HeaderComponentComponent implements OnInit {
      openFlag: boolean = false;
    
      constructor() {}
    
      ngOnInit() {
        console.info('Header component initialised');
      }
    
      openSideNav() {
        this.openFlag = !this.openFlag;
        console.info('Open flag', this.openFlag);
      }
    }
    

    SIDENAV

    import {
      Component,
      Input,
      OnChanges,
      OnInit,
      SimpleChanges,
    } from '@angular/core';
    import { MatButtonModule } from '@angular/material/button';
    import { MatSidenavModule } from '@angular/material/sidenav';
    import { MatIconModule } from '@angular/material/icon';
    import { MatListModule } from '@angular/material/list';
    
    @Component({
      selector: 'app-side-nav',
      standalone: true,
      imports: [MatButtonModule, MatSidenavModule, MatIconModule, MatListModule],
      styles: [
        `
      :host {
        display: block;
        height:100vh;
      }
      .full-height {
        height:100% !important;
      }
      `,
      ],
      template: `
       <mat-sidenav-container autosize class="full-height">
          <mat-sidenav [opened]="openedStatus" mode="push">
            <mat-nav-list>
              <mat-list-item>
              <button mat-button>
                <mat-icon>home</mat-icon>
                Home
              </button>
              </mat-list-item>
    
            <mat-list-item>
              <button mat-button>
                <mat-icon>login</mat-icon>
                Login
              </button>
            </mat-list-item>
    
            <mat-list-item>
              <button mat-button>
                <mat-icon>account</mat-icon>
                Register
              </button>
            </mat-list-item>
          </mat-nav-list>
        </mat-sidenav>
    
    <mat-sidenav-content>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sapien arcu, dictum sed eros a, sollicitudin pellentesque felis. Mauris ultricies, mi in ultricies ullamcorper, metus neque pharetra neque, eget sollicitudin augue sem non sapien. Maecenas a cursus orci. Nam tincidunt facilisis leo, eu vestibulum elit finibus id. Vivamus non erat vitae velit luctus porttitor a in libero. Maecenas at erat sed turpis pretium pretium ultricies quis est. Aenean placerat velit nec orci commodo porttitor. Fusce sodales sagittis nisi a blandit. Fusce nunc nibh, viverra nec congue in, gravida non orci. Praesent sed interdum ex.
    
    Sed non felis vitae nulla cursus aliquam. Curabitur velit diam, commodo ut lectus vitae, pharetra iaculis lorem. Ut feugiat tincidunt massa at egestas. Vestibulum consectetur a nunc eget pretium. Quisque et sem id sapien aliquet tempor. Donec aliquet eget augue vitae dapibus. Suspendisse potenti. Fusce accumsan, libero elementum efficitur rhoncus, enim dolor tristique mauris, in semper leo est et orci. Pellentesque dui sem, cursus in luctus finibus, varius sit amet leo. Praesent vel risus ante. Nulla ultricies lacus nec molestie molestie. Suspendisse tristique sem vitae arcu tempor facilisis.
    
    Nullam in nibh eget lectus molestie consequat. Nulla eget ultrices sem. Aliquam lobortis odio enim, ac cursus ipsum tempus eget. Phasellus porta lorem sem. Ut sit amet iaculis leo. Pellentesque sed magna neque. Aenean pulvinar augue arcu, et pellentesque nulla aliquet eu. Mauris et elementum turpis, id vulputate ex. In eros nunc, vestibulum sed turpis ac, convallis commodo nisi. Vestibulum commodo erat lacus, sit amet mollis elit dapibus a. Nullam nec ex ultricies, laoreet nunc sit amet, ultricies metus. Fusce malesuada finibus mauris, quis porttitor nibh molestie in. Nunc ut rhoncus sem. Curabitur bibendum cursus ultrices. Quisque quis malesuada eros.
    
    Morbi eleifend dolor non dui consectetur, sit amet finibus elit porta. Sed ac ex sit amet ante vestibulum porta. Donec eget consectetur ligula. Sed purus tellus, cursus vitae nunc quis, vulputate pharetra quam. Nam vitae nisl eget purus varius gravida eget sit amet metus. Sed non purus in justo imperdiet volutpat. Donec semper dui a congue sollicitudin. Nunc varius, metus id pulvinar mollis, odio tortor bibendum dolor, in bibendum neque ligula nec dui. Proin nec elementum ex. Maecenas sit amet tempus magna. Etiam id semper magna. Donec sed velit et diam rutrum eleifend et ut purus. Maecenas vitae nunc ligula. Donec ornare nisi eu scelerisque bibendum. Fusce eu erat felis.
    
    Pellentesque pretium ullamcorper ex in pretium. Morbi varius aliquam augue. Ut sed justo vel sem rutrum molestie sit amet at ante. Duis vestibulum augue maximus eros mattis maximus. Fusce porta fermentum arcu, ut efficitur urna lobortis mollis. Quisque feugiat massa finibus urna ornare lobortis ac dapibus quam. Aliquam consectetur magna nec felis consectetur tempus. Mauris placerat nulla vel iaculis dapibus. Ut efficitur dapibus mauris, vitae varius enim accumsan quis. Ut efficitur mauris eget eros volutpat pretium. Maecenas feugiat consectetur dolor, eu fermentum sapien luctus sed. Duis elementum odio in sem rutrum, eu viverra lorem consectetur. Donec eget mi sit amet augue porttitor condimentum sed ut nisl. Proin semper gravida neque, a vehicula ipsum imperdiet sit amet. Aliquam vulputate efficitur risus non vehicula. Vivamus feugiat hendrerit odio, a sodales nunc sagittis et.
    </mat-sidenav-content>
    </mat-sidenav-container>
       `,
    })
    export class SideNavComponent implements OnInit, OnChanges {
      @Input() openedStatus: boolean = false;
    
      constructor() {}
    
      ngOnChanges(changes: SimpleChanges): void {
        console.info('Open Status', changes['openedStatus'].currentValue);
      }
    
      ngOnInit(): void {
        console.info('Side Navigation menu component initialised');
      }
    }
    

    Stackblitz Demo

    Reference stackblitz