Angular Material Side Bar with "Half" side mode
Asked Answered
A

4

32

I am working on the dynamic side bar for our project, basically what we want to do is to set up a dynamic side bar when user click on the side bar it will spread when user click back sidebar should collapse and show only icons (but not totally collapse it will keep the icons) for example before user click the icon. We are using sidenav.toggle()from angular material function which basically closes the sidebar completely and if I don't use toggle() function "Side" mode for navbar does not work. So I want collapse to icon with side mode. (The other reason we need to keep the side mode is that we also need to make sure when user spread the sidebar, right side content should push to right)

enter image description here

After user click the icon enter image description here

Is there a way to do that?

Thanks.

Atomic answered 19/10, 2017 at 17:24 Comment(1)
Keep the side nav open always and have the clock change the width of itBeacham
O
56

Option 1: Generating Automatically:

You can create a navigation component from templates provided by Material itself using 'Angular CLI component schematics'

ng generate @angular/material:nav your-component-name

The above command will generate a new component that includes a toolbar with the app name and a responsive side nav based on Material breakpoints. See more about angular material schematics here


Option 2: Implementing Manually:

To implement that, you just have to refer these two links:

glance through the following code. Implementation will be something like this:

<mat-drawer-container class="example-container mat-typography" autosize>
  <mat-drawer #drawer mode="side" disableClose="true" opened="true">
    <button mat-mini-fab (click)="isExpanded = !isExpanded" color="warn" style="margin: 10px;">
      <mat-icon aria-label="Menu">menu</mat-icon>
    </button>

    <mat-nav-list>
      <mat-list-item>
        <mat-icon mat-list-icon>person</mat-icon>
        <h4 mat-line *ngIf="isExpanded">Management A</h4>
      </mat-list-item>
      <mat-list-item>
        <mat-icon mat-list-icon>assignment</mat-icon>
        <h4 mat-line *ngIf="isExpanded">Management B</h4>
      </mat-list-item>
      <mat-list-item>
        <mat-icon mat-list-icon>domain</mat-icon>
        <h4 mat-line *ngIf="isExpanded">Management C</h4>
      </mat-list-item>
      <mat-list-item>
        <mat-icon mat-list-icon>folder_shared</mat-icon>
        <h4 mat-line *ngIf="isExpanded">Management X</h4>
      </mat-list-item>
    </mat-nav-list>
  </mat-drawer>

  <div class="example-sidenav-content">
    You cards and screen Contents goes here..
    Will be pushed towards right on expanding side navbar.
  </div>
</mat-drawer-container>

Side Navigation Collapsed Side Navigation Expanded

Obsequent answered 20/3, 2019 at 5:17 Comment(6)
it seems that animation is not happening for left bar if used this expanded method. @shaheershukur Can you suggest for animation also?Dissert
Did you add 'BrowserAnimationsModule' ? angular.io/guide/animationsObsequent
Yes, I did implement animations explicitly for margin, width and text. ThanksDissert
As hide/show of the titles is based on *ngIf no animation is happening. To have titles animated use [class.some-animation]="isExpanded" instead of *ngIf. .some-animation { ...fancy css }Arrest
If you've defined an animation openClose as in the example on the angular.io animations guide, then instead of *ngIf="isExpanded" which shaheer shukur used in his snippet above, use [@openClose]="isExpanded ? 'open' : 'closed'".Caputto
the way it close and open doesn't look lively. How to alter that? @shaheershukurGalleywest
S
4

I did this with a bit of CSS

    mat-sidenav:not(.mat-drawer-opened) {
    transform: translate3d(0, 0, 0) !important;
    visibility: visible !important;
    width: 60px !important;
    overflow: hidden;
  }

So when the draw is NOT open, the width of the sidenav is 60px and not 0. Just enough to show your icons.

OK, the next issue is that you'll need to hide a bunch of stuff like button name and other descriptive stuff, for me I need to change the height of the profile image and hide additional text. I did this in the same way as above using the :not selector:

  mat-sidenav:not(.mat-drawer-opened) div.leftNav div.navProfile img {
    width: 40px; margin: 16px 0 0px 0;
  }
  mat-sidenav:not(.mat-drawer-opened) .navTitle,
  mat-sidenav:not(.mat-drawer-opened) .profileTitle {
    display: none;
  }

When collapsed I didn't want to show the button names so I wrapped the name in a *ngIf

 <span class="navName" *ngIf="opened">{{ page?.name }} </span>

This should work, and it does but there is a problem. The ngIf is bound to the opened event and you will notice a delay when the event is firing (to account for it animation) to show your labels when the drawer is open.

To fix this I had to delve into the api of sidenav and found an eventemitter call openedStart and closedStart. I created a new bool in the component class,

showNavLabels: boolean;

then bound the events to this bool in the HTML.

  <mat-sidenav class="sidenav" #sidenav mode="side" [(opened)]="opened"
      (openedStart)='showNavLabels = !showNavLabels'
      (closedStart)='showNavLabels = !showNavLabels' >

I am sure there is better way as I am not that experienced with Angular yet.

I hope it helps you out.

Sleigh answered 10/2, 2020 at 11:53 Comment(0)
E
2

I created an example based on scss. Maybe someone can help to create the mobile version according to this sample.

  • Step 1: Add below style to styles.scss
// src/styles.scss
:root {
  --menu-width-open: 200px;
  --menu-width-closed: 64px;
}

.mat-drawer-container {
  .mat-drawer {
    box-sizing: content-box;
    width: var(--menu-width-open);
    transition: all 0.3s ease-in-out !important;
  }

  .mat-drawer-content {
    // transform: translateX(200px);
    margin-left: var(--menu-width-open) !important;
    transition: all 0.3s ease-in-out !important;
  }

  &.container-closed {
    .mat-drawer {
      width: var(--menu-width-closed);
    }

    .mat-drawer-content {
      // transform: translateX(64px) !important;
      margin-left: var(--menu-width-closed) !important;
    }
  }
}
  • Step 2: Add drawer to app.componenet.html
<mat-drawer-container class="example-container" autosize [ngClass]="{ 'container-closed': !showFiller }">
  <mat-drawer #drawer class="example-sidenav" mode="side" disableClose="true" opened="true">
    <button (click)="showFiller = !showFiller" mat-raised-button>click</button>
  </mat-drawer>
  <div class="example-sidenav-content">
    <router-outlet></router-outlet>
    <button type="button" mat-button (click)="drawer.toggle()">Toggle sidenav</button>
  </div>
</mat-drawer-container>
  • Step 3: And add showFiller = false; to app.component.ts file.
// app.component.ts
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  showFiller = false;
}
Ellamaeellan answered 30/7, 2022 at 22:0 Comment(0)
C
0

There is a feature request for this https://github.com/angular/material2/issues/1728

if you read the comments you'll also find a few examples on how to implement it yourself while it's not officialy available.

Carny answered 25/1, 2018 at 20:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.