如何将sidenav(mat-drawer)状态保存到Angular Material中的localstorage?

Posted

技术标签:

【中文标题】如何将sidenav(mat-drawer)状态保存到Angular Material中的localstorage?【英文标题】:How to save sidenav (mat-drawer) state to localstorage in Angular Material? 【发布时间】:2021-02-16 06:13:09 【问题描述】:

我对 Angular Material 中的垫子抽屉有疑问。我想将我的状态保存到 localstorage,但 mat-drawer 总是打开的。

Sidenav 在没有文字的垫子图标时有展开部分和关闭展开部分。当您点击底部按钮 Hide 时,sidenav 为 Close,但在刷新页面后 Sidenav 再次展开(但在 localstorage 中已关闭)。

看起来像这样:

Opened expanded mat drawer

Closed mat drawer

Sidenav is open but in local storage is closed

你知道如何解决这个问题吗?谢谢!

源代码:

app.component.html

<mat-drawer-container class="content-container" autosize >
 <mat-drawer
  mode="side"
  class="sidenav"
  disableClose="true"
  opened="true">
<div class="sidenav-container">
<mat-nav-list>
      <a class="nav-item nav-link" mat-list-item routerLink="/private/dashboard" routerLinkActive="active" [routerLinkActiveOptions]=" exact: true ">
        <mat-icon style="padding-right:5px;"  matTooltipPosition="right" [matTooltipDisabled]="disabledTooltip">dashboard</mat-icon>
        <span *ngIf="isExpanded">Dashboard</span>
      </a>

      <a class="nav-item nav-link" mat-list-item routerLink="/private/companies" routerLinkActive="active">
        <mat-icon style="padding-right:5px;">stars</mat-icon>
        <span *ngIf="isExpanded">Subjects</span>
      </a>

      <a class="nav-item nav-link" mat-list-item routerLink="/private/users" routerLinkActive="active">
        <mat-icon style="padding-right:5px;">group</mat-icon>
        <span *ngIf="isExpanded">Users</span>
      </a>

      <a class="nav-item nav-link" mat-list-item routerLink="/private/api-customers" routerLinkActive="active">
        <mat-icon style="padding-right:5px;">beenhere</mat-icon>
        <span *ngIf="isExpanded">Clients</span>
      </a>

      <a class="nav-item nav-link" mat-list-item routerLink="/private/applications" routerLinkActive="active">
        <mat-icon style="padding-right:5px;">apps</mat-icon>
        <span *ngIf="isExpanded">Apps</span>
      </a>

      <a class="nav-item nav-link" mat-list-item routerLink="/private/calendar" routerLinkActive="active">
        <mat-icon style="padding-right:5px;">calendar_today</mat-icon>
        <span *ngIf="isExpanded">Calendar</span>
      </a>
</mat-nav-list>
        <div class="sidenav-bottom">
          <mat-nav-list>
            <a class="nav-item nav-link" mat-list-item (click)="onSidenavToggle()">
              <mat-icon *ngIf="isExpanded">arrow_back_ios</mat-icon>
              <mat-icon *ngIf="!isExpanded">arrow_forward_ios</mat-icon>
              <span *ngIf="isExpanded">Hide</span>
            </a>
          </mat-nav-list>
        </div>
    </mat-drawer>
<mat-drawer-content>
Page content
</mat-drawer-content>
</mat-drawer-container>

app.component.ts

import Component, HostListener, Inject, OnInit from '@angular/core';
import  Router  from '@angular/router';
import Subject from 'rxjs';

@Component(
  selector: 'app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
)

export class AppComponent  

  isExpanded = true;
  constructor(
  private sidenavService: SidebarService) 
  this.sidenavService.setHideSidebar(this.sidenavService.isHideSidebar());
  
  onSidenavToggle() 
    this.isExpanded = !this.isExpanded;
    this.sidenavService.setHideSidebar(!this.sidenavService.isHideSidebar());
    this.sidenavService.sideBarState$.next(this.isExpanded);
  

sidebar.service.ts

import  Injectable  from '@angular/core';
import  Subject  from 'rxjs';


@Injectable()
export class SidebarService 

  public sideBarState$: Subject<boolean> = new Subject<boolean>();

  constructor() 
    const initialValue = localStorage.getItem('isExpanded');
    this.sideBarState$.next(initialValue === 'close');
  

  getHideSidebar(): Subject<boolean> 
    return this.sideBarState$;
  

  setHideSidebar(newValue: boolean): void 
    localStorage.setItem('isExpanded', newValue ? 'close' : 'open');
    this.sideBarState$.next(newValue);
  

  isHideSidebar(): boolean 
    return localStorage.getItem('isExpanded') === 'close';
  


【问题讨论】:

【参考方案1】:

原来问题出在组件中的isExpanded。该值被硬编码为true,与服务(或存储在LOCALSTORAGE中的值)无关。

其他一些建议是单独使用 Subject 值作为 isExpanded 应该是的一个真正来源(使用 EMIT 值,不要自己设置)。如果您将isExpanded 存储为true 或false,而不是openclose,也会更有意义。变量名表明该值为真或假。

import Component, HostListener, Inject, OnInit from '@angular/core';
import  Router  from '@angular/router';
import Subject from 'rxjs';

@Component(
  selector: 'app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
)

export class AppComponent  

  isExpanded;
  constructor(
  private sidenavService: SidebarService) 
  isExpanded = !this.sidenavService.isHideSidebar();
  
  onSidenavToggle() 
    this.isExpanded = !this.isExpanded;
    this.sidenavService.setHideSidebar(!this.sidenavService.isHideSidebar());
    this.sidenavService.sideBarState$.next(this.isExpanded);
  

【讨论】:

以上是关于如何将sidenav(mat-drawer)状态保存到Angular Material中的localstorage?的主要内容,如果未能解决你的问题,请参考以下文章

在mat-sidenav组件的'closing'事件中更改状态时,角度动画不会触发?

Reactjs - 将状态值从一个组件传递到另一个组件

Angular 6,7 如何将默认主题颜色应用于 mat-sidenav 背景?

全高弯曲的角材料垫抽屉,内容自动溢出

Angular 5 Material 如何将下拉菜单添加到多级轮播样式的 SideNav?

将应用内容放在 mat-sidenav-content 中