Search code examples
angularangular-materialangular5angular-material2sidenav

Angular 5 Material Multi-level Carousel style SideNav Menu (no dropdown)


I managed to do that in my side with Angular Material, it worked with sub-menus that were deployed with dropdowns, but I'm looking for a way to make them not "Dropdowns", I'm looking for them to be like a kind of transition towards right, Something like this:

https://jmouriz.github.io/angular-material-multilevel-menu/demo/demo.html#!/demo/views/item-2

But this one is done in AngularJS 1.X. I am using Angular 5, does anyone come up with any way or where to start? Thank you!


Solution

  • After looking into this further I felt the original solution was overtly complicated, and there had to be a better way.

    • The original approach was to control the hierarchy mainly from the view...
    • This was the wrong approach.

    The revised approach is based on the concept of driving the view based on array hierarchy... this makes for a much cleaner solution with better scale-ability.


    Define array hierarchy... the key here is to assign options with sub menus to rootTab indexes that will hold the sub menu options when clicked..

    rootTabs = [
        {
          id: 0,
          options: [
            { option: 'Home' },
            { option: 'Parámetros' },
            { option: 'Operativa' },
            { option: 'Productos' },
            { option: 'Invocación Servicios', rootTab: 1 }
          ]
        },
        {
          id: 1,
          options: [
            { option: 'Portal 1', rootTab: 2 },
            { option: 'Portal 2', rootTab: 4 },
            { option: 'Portal 3', rootTab: 5 }
          ]
        },
        {
          id: 2,
          options: [
            { option: 'Service 1 Item1', route: '/Submenu1' },
            { option: 'Service 1 Item2', route: '/Submenu2' },
            { option: 'Service 1 Item3', route: '/Submenu3' },
            { option: 'Service 1 Item4', route: '/Submenu4' },
            { option: 'Service 1 Item5', route: '/Submenu5' },
            { option: 'Invocación Servicios', rootTab: 3 }
          ]
        },
        {
          id: 3, options: [
            { option: 'put additional options here' }
          ]
        },
        {
          id: 4,
          options: [
            { option: 'Service 2 Item1', route: '/Submenu1' },
            { option: 'Service 2 Item2', route: '/Submenu2' },
            { option: 'Service 2 Item3', route: '/Submenu3' },
            { option: 'Service 2 Item4', route: '/Submenu4' },
            { option: 'Service 2 Item5', route: '/Submenu5' },
          ]
        },
        {
          id: 5,
          options: [
            { option: 'Service 3 Item1', route: '/Submenu1' },
            { option: 'Service 3 Item2', route: '/Submenu2' },
            { option: 'Service 3 Item3', route: '/Submenu3' },
            { option: 'Service 3 Item4', route: '/Submenu4' },
            { option: 'Service 3 Item5', route: '/Submenu5' },
          ]
        }
      ]
    

    Create component methods to handle menu state via UI interaction.

    rootSelected(optionIndex, optionRootIndex, rootOption) {
        this.numItemsSelected++;
        this.previousRootTab = this.currentSelectedRootTab;
        this.currentSelectedRootTab = optionRootIndex;
        this.indexClicked = optionIndex;
        if (!this.breadcrumb1) {
          this.breadcrumb1 = rootOption
        } else if (!this.breadcrumb2) {
          this.breadcrumb2 = rootOption
        } else {
          this.breadcrumb3 = rootOption
        }
      }
    
      back2Main() {
        this.currentSelectedRootTab = 0;
        this.previousRootTab = 0;
        this.indexClicked = 0;
    
        this.numItemsSelected = 0;
        this.breadcrumb1 = null;
        this.breadcrumb2 = null;
        this.breadcrumb3 = null;
      }
    
      toBreadcrum1() {
        if (this.numItemsSelected > 1) {
          this.currentSelectedRootTab = this.breadcrumb1.rootTab;
          this.breadcrumb2 = null;
          this.numItemsSelected--
        }
      }
    
      toBreadcrum2() {
        if (this.numItemsSelected > 2) {
          this.currentSelectedRootTab = this.breadcrumb2.rootTab;
          this.breadcrumb3 = null;
          this.numItemsSelected--
        }
      }
    

    Wire it all up in the template

    <div style="display: flex;flex-direction: row;margin:1% ;height:30px;">
        <div routerLink="/" routerLinkActive="active" (click)="back2Main()" style="cursor:pointer" class="vertical-align-text">Main</div>
        <div *ngIf="numItemsSelected >= 1">&nbsp;<mat-icon>chevron_right</mat-icon></div>
        <span *ngIf="numItemsSelected >= 1" routerLink="/" routerLinkActive="active" class="vertical-align-text" style="cursor:pointer;vertical-align: middle;" (click)="toBreadcrum1();">&nbsp;{{breadcrumb1.option}}</span>
        <div *ngIf="numItemsSelected >= 2">&nbsp;<mat-icon>chevron_right</mat-icon></div>
       <span *ngIf="numItemsSelected >= 2" routerLink="/" routerLinkActive="active" class="vertical-align-text" style="cursor:pointer" (click)="toBreadcrum2();">&nbsp;{{breadcrumb2.option}}</span>
        <div *ngIf="numItemsSelected >= 3">&nbsp;<mat-icon>chevron_right</mat-icon></div>
       <span *ngIf="numItemsSelected >= 3" routerLink="/" routerLinkActive="active" class="vertical-align-text" style="cursor:pointer" (click)="toBreadcrum3();">&nbsp;{{breadcrumb3.option}}</span>
       </div>
    
    
    <div style="display: flex;flex-direction: row;background-color:white; height:100vh">
        <mat-tab-group class="navigation-tabs" [selectedIndex]="currentSelectedRootTab" dynamicHeight style="width:25vw; background-color:lightgray">
            <mat-tab *ngFor="let rootTab of rootTabs; let rootIndex = index" [label]="rootIndex">
                <mat-nav-list>
            <div *ngFor="let rootOption of rootTab.options; let optionIndex = index;">       
              <a mat-list-item *ngIf="!rootOption.rootTab" [routerLink]="rootOption.route" routerLinkActive="active">{{rootOption.option}}</a>
              <a mat-list-item style="width:100%" *ngIf="rootOption.rootTab" (click)="rootSelected(optionIndex, rootOption.rootTab, rootOption)">{{rootOption.option}}<div><mat-icon style="padding-left:20%;vertical-align: middle;">chevron_right</mat-icon></div></a>
            </div> 
                </mat-nav-list>
            </mat-tab>
        </mat-tab-group>
      <div style="margin:auto">
        <router-outlet></router-outlet> 
      </div>
    </div>
    

    Stackblitz

    https://stackblitz.com/edit/angular-x5xefi-gmzy46?embed=1&file=app/tab-group-basic-example.html