如何通过单击具有RouterLink指令的元素来关闭Material SideNav?

Nic*_* N. 9 angular-material2 angular

我使用角度4与角度材料相结合.

我正在使用sidenav容器路由器和自定义生成的菜单:

<mat-sidenav-container>
<mat-sidenav #sidenav>
    <app-menu></app-menu>
</mat-sidenav>
<router-outlet></router-outlet>
</mat-sidenav-container>
Run Code Online (Sandbox Code Playgroud)

在菜单组件内部我使用默认的角度4路由器链接:

<ul>
  <li *ngFor="let hero of heroes">
    <a mat-button [routerLink]="['/hero/', hero.id]" queryParamsHandling="merge">
      {{hero.name}}
    </a>
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

我想要做的是Material sidenav在点击其中一个路由器链接时关闭它.

我可以向你保证,如果没有点击事件路由工作正常,它就不会关闭我的sidenav,因为路由器插座位于侧面导航内.

但是,当我添加(click)="sidenav.close()"到a我的整个页面突然刷新,而不是只是跟随路由器链接.

我尝试了很多东西,但我似乎无法弄明白,希望有人可以帮忙!

Avi*_* P. 22

这是一个完整的解决方案,基于Angular Material的原理图生成sidenav布局组件.通过考虑我们是否在手机设备上,并确保侧线仅在手机设备上关闭,这个答案改进了以前的答案.

几点:

  1. 该组件是使用Angular Materials 导航原理图生成的.
  2. 我打电话给我的组件my-menu,你可以使用任何其他名称.
  3. 如果我们不在手机设备上,sidenav将关闭,这是使用rxjs运算符withLatestFrom结合isHandset$原理图生成的流完成的.
import { Component, ViewChild } from '@angular/core';
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, filter, withLatestFrom } from 'rxjs/operators';
import { Router, NavigationEnd } from '@angular/router';
import { MatSidenav } from '@angular/material';

@Component({
  selector: 'app-my-menu',
  templateUrl: './my-menu.component.html',
  styleUrls: ['./my-menu.component.css']
})
export class MyMenuComponent {
  @ViewChild('drawer') drawer: MatSidenav;

  isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
    .pipe(
      map(result => result.matches)
    );

  constructor(private breakpointObserver: BreakpointObserver,
    router: Router) {
    router.events.pipe(
      withLatestFrom(this.isHandset$),
      filter(([a, b]) => b && a instanceof NavigationEnd)
    ).subscribe(_ => this.drawer.close());
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,效果很好。然而,就我而言,关闭抽屉后,菜单按钮保持较暗的颜色(周围有一个圆形)。菜单按钮位于 &lt;mat-toolbar&gt; 内,而 &lt;mat-toolbar&gt; 位于 &lt;mat-sidenav-content&gt; 内。这个圆圈的颜色似乎与涟漪效应有关。知道如何解决这个问题吗?(但是,一旦我们单击任意位置,圆圈就会消失,但我希望它在没有任何用户操作的情况下消失)。 (3认同)
  • 很好的解决方案。从技术上讲,组件的视图仅在生命周期挂钩[AfterViewInit](https://angular.io/api/core/AfterViewInit)之后才完全初始化,但是我想这行得通,因为路由器事件无论如何都只会在此之后发送。 (2认同)
  • 这段代码很难理解,但是有效。从8+开始,您应该使用@ViewChild('drawer',{static:true})抽屉:MatSidenav;` (2认同)

小智 10

添加(click)="sidenav.close()"到 mat-sidenav

<mat-sidenav #sidenav mode="side" class="app-sidenav" (click)="sidenav.close()">
Run Code Online (Sandbox Code Playgroud)


ish*_*ood 9

我创建了一个服务,以便可以从各个组件控制sidenav。我遵循了这个例子。

然后只需观察路由器的事件并根据需要关闭即可。在app.component.ts中:

this.router.events.subscribe(event => {
  // close sidenav on routing
  this.sidenavService.close();
});
Run Code Online (Sandbox Code Playgroud)

如果您想要关闭的sidenav这不起作用,只有特定的链接,但该服务本身将有助于这一点。


Sha*_*oon 8

您不需要为此提供服务。这是一个简单的解决方案。

<mat-sidenav-container [hasBackdrop]="true">
                <mat-sidenav #sidenav mode="side" class="sideNavigation">
                        <mat-nav-list>
                                <a mat-list-item routerLink="" (click)="sidenav.close()"> bar</a>
                                <a mat-list-item routerLink="/bar" (click)="sidenav.close()">foo</a>
                                <a mat-list-item routerLink="/foo" (click)="sidenav.close()">whatever</a>
                                <a mat-list-item routerLink="/something1" (click)="sidenav.close()">SomePage</a>
                                <a mat-list-item routerLink="/something2" (click)="sidenav.close()">Some Page</a>
                        </mat-nav-list>
                </mat-sidenav>
                <mat-sidenav-content>
                        <mat-toolbar color="accent">
                                <mat-icon (click)="sidenav.toggle()">menu</mat-icon> 
                                <div class="divider"></div>
                                <img class="img" src="../assets/img/logo.png" alt="logo" (click)="goHome()" />
                        </mat-toolbar>
                        <router-outlet></router-outlet>
                </mat-sidenav-content>
        </mat-sidenav-container>
Run Code Online (Sandbox Code Playgroud)

您所做的就是(click)="sidenav.close()"与routerLink="/whatever/path/here"作品一起添加。这将关闭sidenav指向页面。

  • 对于那些抱怨重复的人,您只需将 `&lt;mat-nav-list&gt;` 更改为 `&lt;mat-nav-list (click)="sidenav.close()"&gt;` 并删除所有 `(click )="sidenav.close()"` 来自 `mat-list-item` (2认同)

Nic*_* N. 5

受到@isherwood 回答的启发,我想出了一个解决方案:

我创建了以下服务:

import { Injectable } from '@angular/core';
import { MatSidenav } from '@angular/material';

@Injectable()
export class SidenavService {

  public sideNav:MatSidenav;
  constructor() { }
}
Run Code Online (Sandbox Code Playgroud)

我更改了我的应用程序组件以在上述服务中设置 sideNav 属性。

export class AppComponent implements OnInit {
  title = 'app';

  @ViewChild('sidenav') public sideNav:MatSidenav;
  constructor(private sidenavService: SidenavService) {      
  }

  ngOnInit() {
    this.sidenavService.sideNav = this.sideNav;
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在函数中实现和设置非常重要。OnInitsidenavService.sideNavngOnInit

然后你可以在任何你想要的地方使用你的 sideNavService。就我而言,我仅在我在侧边导航菜单中实际链接的组件中使用它。

例子:

 export class HeroComponent implements OnInit {

  constructor(private sidenavService: SidenavService) {      
  }

  ngOnInit() {
    this.sidenavService.sideNav.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

您可能希望在更改参数而不是在 init 时执行此操作,但您明白了。