Поддерживать состояние расширения Sidenav после изменения маршрута - PullRequest
0 голосов
/ 07 февраля 2020

Есть ли способ сохранить состояние расширенного узла sidenav без использования какого-либо управления состоянием? На данный момент расширенный узел sidenav будет сбрасываться каждый раз при изменении маршрута. Кажется, что компонент navbar разрушается снова и снова.

enter image description here

navbar.component. html

<mat-sidenav-container [hasBackdrop]="true" autosize>
  <mat-sidenav fixedTopGap="60" fixedInViewport="true" #sidenav mode="over">
    <mat-list-item>Modules</mat-list-item>

    <mat-tree
      [dataSource]="dataSource"
      [treeControl]="treeControl"
      class="tree"
    >
      <ng-container *matTreeNodeDef="let node">
        <mat-tree-node routerLinkActive="active" matTreeNodeToggle>
          <a class="full-content" [routerLink]="[node.link]" mat-icon-button>
            <div style="text-align: left;">
              <mat-icon mat-icon-button>{{ node.icon }}</mat-icon>
              <mat-label>{{ node.name }}</mat-label>
            </div>
          </a>
        </mat-tree-node>
      </ng-container>

      <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
        <li>
          <div class="mat-tree-node">
            <button
              matTreeNodeToggle
              class="full-content-button"
              mat-icon-button
              [attr.aria-label]="'toggle ' + node.name"
              (click)="changeState(node)"
            >
              <mat-icon class="mat-icon-rt1-mirror">
                {{
                  treeControl.isExpanded(node) ? 'expand_less' : 'expand_more'
                }}
              </mat-icon>
              {{ node.name }}
            </button>
          </div>

          <ul [class.tree-invisible]="!treeControl.isExpanded(node)">
            <ng-container matTreeNodeOutlet></ng-container>
          </ul>
          <hr />
        </li>
      </mat-nested-tree-node>
    </mat-tree>
  </mat-sidenav>

  <mat-sidenav-content (scroll)="onScroll($event)">
    <router-outlet></router-outlet>
  </mat-sidenav-content>
</mat-sidenav-container>

navbar.component.ts

import * as CryptoJS from "crypto-js";
import cloneDeep from 'lodash.clonedeep';
import { ActivatedRoute, Data, Router, UrlSegment } from '@angular/router';
import {
  AfterViewInit,
  Component,
  OnDestroy,
  OnInit,
  ViewChild
} from '@angular/core';
import { BehaviorSubject, combineLatest, Subscription } from 'rxjs';
import { excludedModule } from 'src/app/shared/type-casting/enum/navbar-exclude.enum';
import { INavBarMenu } from '../../../models/modules/general/navbar/NavBar.model';
import { LocalStorageService } from './../../../util/localStorage/local-storage.service';
import { MatSidenav } from '@angular/material';
import { NavBarService } from './../../../../core/services/general/navbar/navbar.service';
import { NestedTreeControl } from '@angular/cdk/tree';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild('sidenav') _sidenav: MatSidenav;

  /** @value Cater opacity value of '0' & '1' */
  private isFooterShownSubject = new BehaviorSubject<number>(+false);
  readonly isFooterShown$ = this.isFooterShownSubject.asObservable();

  public dataSource: INavBarMenu[];
  public treeControl = new NestedTreeControl<INavBarMenu>(
    node => node.children
  );
  private enumExcludedModule = Object.values(excludedModule);
  private subscriptions = new Subscription();
  private route: Data;

  constructor(
    private _navBarService: NavBarService,
    private _acRoute: ActivatedRoute,
    private _router: Router,
    private _localStorage: LocalStorageService
  ) {
    this.route = _acRoute.snapshot.root.firstChild.children[0].children[0];

    /** @execute multiple subscription in parallel, then take only latest subscription */
    combineLatest(this.getMenuDetails(), _acRoute.url).subscribe(
      ([res]: [INavBarMenu[], UrlSegment[]]) => {
        const clonedRes: INavBarMenu[] = cloneDeep(res);

        const accessRights = CryptoJS.AES.encrypt(
           JSON.stringify(clonedRes),
           "Secret Passphrase"
          ); 
        localStorage.setItem('accessRights', accessRights);

        /** @mutation - changed object reference of clonedRes, lastly this.dataSource assigned value of mutated clonedRes */
        clonedRes.forEach(el =>
          this.enumExcludedModule.forEach(
            exclude =>
              (el.children = Object.values(el.children).filter(
                value => value.link !== exclude
              ))
          )
        );
        this.dataSource = clonedRes;
      }
    );
  }

  onScroll(event: any) {
    /** @logic visible height + pixel scrolled >= total height */
    event.target.offsetHeight + event.target.scrollTop >=
    event.target.scrollHeight
      ? this.isFooterShownSubject.next(+1)
      : this.isFooterShownSubject.next(+0);
  }

  hasChild = (_: number, node: INavBarMenu) =>
    !!node.children && node.children.length > 0;

  ngOnInit() {}

  goHome() {
    this._router.navigate(['/homepage']);
  }

  logout() {
    localStorage.clear();
    this._router.navigate(['/login']);
  }

  ngAfterViewInit(): void {
  }

  changeState(node) {
    console.log(node);
  }

  ngOnDestroy(): void {
    this.subscriptions.unsubscribe();
  }
}

NavBar.model.ts

export class INavBarMenu {
  constructor(

    public id: number,
    public name: string,

    public pView: string,
    public pAdd: string,
    public pEdit: string,
    public pDelete: string,

    public link?: string,
    public icon?: string,
    public isExpanded?: boolean,
    public children?: INavBarMenu []
    ) {}
}

Образец данных

{"id":12,"icon":null,"name":"Prod. Control","nameDesc":null,"pID":10,"link":null,"pView":"true","pAdd":"true","pEdit":"true","pDelete":"true","children":[{"id":33,"icon":null,"name":"PO Listing","nameDesc":null,"pID":12,"link":"/productionorder","pView":"true","pAdd":"true","pEdit":"true","pDelete":"true"},{"id":26,"icon":null,"name":"Design Layout","nameDesc":null,"pID":12,"link":"/designlayout","pView":"true","pAdd":"true","pEdit":"true","pDelete":"true"}]}

1 Ответ

0 голосов
/ 02 марта 2020

Мы нашли способ обойти это через несколько дней после того, как я опубликовал это.

Просто включите BehaviorSubject в службу для хранения расширенного индекса dataNodes, тогда все остальное очевидно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...