Angular Material侧边栏点击遮罩区域关闭功能实现问题
问题:Angular Material侧边栏点击遮罩无法关闭,结合NgRx实现布局
我是Angular Material、NgRx及现代Angular的新手,正在实现一个基础头部布局:包含带标题和菜单图标的Toolbar,以及承载链接的Sidenav。需求是:
- 点击菜单图标打开侧边栏
- 点击侧边栏外的遮罩区域(backdrop)关闭侧边栏
我参考NgRx示例应用尝试实现,但通过(click)和(backdropClick)事件在Sidenav容器上触发事件时,功能未成功实现。相关代码如下:
app.component.ts
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import * as fromRoot from '@client-app/reducers'; import { LayoutActions } from '@client-app/core/actions'; @Component({ selector: 'app-root', changeDetection: ChangeDetectionStrategy.OnPush, template: ` <app-layout (closeMenu)="closeSidenav()"> <app-toolbar (openMenu)="openSidenav()">Memories</app-toolbar> <app-sidenav [open]="(showSidenav$ | async)!"> </app-sidenav> <router-outlet></router-outlet> </app-layout> `, }) export class AppComponent { showSidenav$: Observable<boolean>; constructor(private store: Store) { this.showSidenav$ = this.store.select(fromRoot.selectShowSidenav); } closeSidenav() { this.store.dispatch(LayoutActions.closeSidenav()); } openSidenav() { this.store.dispatch(LayoutActions.openSidenav()); } }
layout.component.ts
import { Component, EventEmitter, Output } from '@angular/core'; @Component({ selector: 'app-layout', template: ` <mat-sidenav-container fullscreen> <ng-content></ng-content> </mat-sidenav-container> `, }) export class LayoutComponent { @Output() closeMenu = new EventEmitter<void>; }
sidenav.component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'app-sidenav', template: ` <mat-sidenav position="end" [opened]="open" > <mat-nav-list> <a mat-list-item href="login">Login</a> <a mat-list-item href="signup">Signup</a> </mat-nav-list> </mat-sidenav> `, styles: [ ` mat-sidenav { width: 200px; } `, ], }) export class SidenavComponent { @Input() open = false; }
toolbar.component.ts
import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-toolbar', template: ` <mat-toolbar color="primary"> <ng-content></ng-content> <button mat-icon-button (click)="openMenu.emit()" aria-label="menu"> <mat-icon>menu</mat-icon> </button> </mat-toolbar> `, styles: [ ` mat-toolbar { display: flex; justify-content: space-between; } `, ], }) export class ToolbarComponent { @Output() openMenu = new EventEmitter<void>; }
解决方案
问题核心是未正确监听遮罩点击事件,且mat-sidenav默认模式不生成遮罩。以下是具体修改步骤:
1. 给LayoutComponent添加遮罩点击监听
在mat-sidenav-container上绑定(backdropClick)事件,触发closeMenu输出:
// layout.component.ts @Component({ selector: 'app-layout', template: ` <mat-sidenav-container fullscreen (backdropClick)="closeMenu.emit()"> <ng-content></ng-content> </mat-sidenav-container> `, }) export class LayoutComponent { @Output() closeMenu = new EventEmitter<void>(); // 补充分号修正语法 }
2. 给SidenavComponent设置mode="over"
mat-sidenav默认mode="side"(侧边固定显示),不会生成遮罩。设置为mode="over"才能在侧边栏弹出时显示遮罩:
// sidenav.component.ts @Component({ selector: 'app-sidenav', template: ` <mat-sidenav position="end" [opened]="open" mode="over" <!-- 添加此行 --> > <mat-nav-list> <a mat-list-item href="login">Login</a> <a mat-list-item href="signup">Signup</a> </mat-nav-list> </mat-sidenav> `, styles: [ ` mat-sidenav { width: 200px; } `, ], }) export class SidenavComponent { @Input() open = false; }
3. 修正语法细节
给所有EventEmitter定义补充分号,保证语法合规:
// toolbar.component.ts @Output() openMenu = new EventEmitter<void>();
修改完成后,点击菜单图标会触发NgRx的openSidenav动作打开侧边栏,点击遮罩区域会触发closeSidenav动作关闭侧边栏,完全符合需求。
内容的提问来源于stack exchange,提问作者orangecheese
相关产品推荐
相关产品推荐

