angular - Angular 6 - 如何使用按钮从另一个组件切换 sidenav
问题描述
<mat-drawer-content class="btmm md-sidenav-right">
<button (click)="sideNav.toggle()" mat-button>Toggle SideNav</button>
</mat-drawer-content>
上面的代码是一个组件中的按钮
<mat-drawer #sideNav mode="push" opened="false" position="end" class="navsize _md-sidenav-backdrop">
Drawer content
</mat-drawer>
此代码希望在另一个组件中
我该怎么做请用我的代码做并解释它
解决方案
要从另一个组件切换 sidenav,您需要:
- 属性装饰器@ViewChild。
- 完成此功能的服务。
例如,假设您有一个管理所有标头的标头组件和几个用于每个标头的 sidenav 组件。
所以在:
标题
header.component.html
<mat-toolbar color="primary" class="example-toolbar" [ngSwitch]="headerType">
<!-- HEADER_1 -->
<mat-toolbar-row color="warn" class="example-toolbar" *ngSwitchCase="1">
<button mat-icon-button (click)="toggleSidenav()">
<mat-icon>menu</mat-icon>
</button>
<h1 class="example-app-name">HEADER 1</h1>
</mat-toolbar-row>
<!-- HEADER_2 -->
<mat-toolbar-row color="warn" class="example-toolbar" *ngSwitchCase="2">
<button mat-icon-button (click)="toggleSidenav()">
<mat-icon>menu</mat-icon>
</button>
<h1 class="example-app-name">HEADER 2</h1>
</mat-toolbar-row>
<!-- DEFAULT HEADER -->
<mat-toolbar-row *ngSwitchDefault>
<h1 class="example-app-name">DEFAULT HEADER</h1>
</mat-toolbar-row>
</mat-toolbar>
在 header.component.ts 中:
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { MediaMatcher } from '@angular/cdk/layout';
import { SidenavService } from '../services/sidenav.service';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
headerType: number;
toggleActive = false;
mobileQuery: MediaQueryList;
private _mobileQueryListener: () => void;
constructor(private sidenav: SidenavService,
changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
// to change the varible in the *ngSwitch directive
this.newHeader(1);
// this.newHeader(2);
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
newHeader(headerType: number) {
this.headerType = headerType;
}
toggleSidenav() {
this.toggleActive = !this.toggleActive;
this.sidenav.toggle();
}
}
侧导航
在 sidenav.service.ts 中:
import { Injectable } from '@angular/core';
import { MatSidenav } from '@angular/material';
@Injectable({
providedIn: 'root'
})
export class SidenavService {
private sidenav: MatSidenav;
constructor() { }
public setSidenav(sidenav: MatSidenav) {
this.sidenav = sidenav;
}
public open() {
return this.sidenav.open();
}
public close() {
return this.sidenav.close();
}
public toggle(): void {
this.sidenav.toggle();
}
}
假设每个标题都有多个 sidenav 组件:
在 sidenav1.component.html 中:
<div class="example-container" [class.example-is-mobile]="mobileQuery.matches">
<app-header></app-header>
<mat-sidenav-container class="example-sidenav-container" [style.marginTop.px]="mobileQuery.matches ? 56 : 0">
<mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches"
fixedTopGap="56">
<mat-nav-list>
<a mat-list-item routerLink="{{nav.link}}" *ngFor="let nav of fillerNav">{{nav.name}}</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
在 sidenav1.component.ts 中:
import { MediaMatcher } from '@angular/cdk/layout';
import { Component, OnInit, OnDestroy, ChangeDetectorRef, ViewChild } from '@angular/core';
import { MatSidenav } from '@angular/material';
import { SidenavService } from 'src/app/services/sidenav.service';
@Component({
selector: 'app-sidenav1',
templateUrl: './sidenav1.component.html',
styleUrls: ['./sidenav1.component.scss']
})
export class Sidenav1Component implements OnInit, OnDestroy {
sidenavList1: Array<{ name: string, link: string }> = [
{ 'name': 'My profile', 'link': 'profile' },
{ 'name': 'Settings', 'link': 'settings' },
{ 'name': 'My messages', 'link': 'messages' },
{ 'name': 'Notifications', 'link': 'notifications' }];
mobileQuery: MediaQueryList;
fillerNav = Array.from(this.sidenavList1);
fillerContent = Array.from({ length: 6 }, () =>
` --text content-- `);
private _mobileQueryListener: () => void;
@ViewChild('snav') public sidenav: MatSidenav;
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, private sidenavService: SidenavService) {
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
ngOnInit() {
this.sidenavService.setSidenav(this.sidenav);
}
ngOnDestroy(): void {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
}
对于另一个sidenav,您可以重现相同的过程...
应用组件
在 app.component.ts 中:
export class AppComponent {
title = 'my-app';
headerType: number;
constructor() {
this.newHeader(1);
}
newHeader(headerType: string) {
this.headerType = headerType;
}
}
在 app.component.html
<div [ngSwitch]="headerType">
<div *ngSwitchCase="1">
<app-sidenav-1></app-sidenav-1>
</div>
<div *ngSwitchCase="2">
<app-sidenav-2></app-sidenav-2>
</div>
<div *ngSwitchDefault>
Default content
<router-outlet></router-outlet>
</div>
</div>
推荐阅读
- widget - 从 kpis 查询构建表小部件
- python - 使用 API 填充 Excel 文件以在 Python 中跟踪卡片价格
- python-3.x - 将文件名散列成单词的组合
- html - 为什么我的元素在我的导航器中不是水平的
- python - Python (Turtle) 应用程序窗口退出时报错
- python - 我不了解此代码中迭代变量 (i,j) 的功能
- ffmpeg - pyav / ffmpeg / libav 选择 P 帧和 B 帧的数量
- c# - C# Http 请求与 json 中的数组
- javascript - 在加载的 iframe 处设置本地存储
- r - 每隔一个垂直月着色一次,白色和灰色交替