Angular 6-如何使用按钮从另一个组件切换sidenav

时间:2019-01-05 05:26:14

标签: angular angular-material angular6

<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>
  

此代码想包含在另一个组件中

我该怎么做,请对我的代码进行说明并解释

2 个答案:

答案 0 :(得分:0)

如果您的组件不直接相关(例如,路线),也许您可​​以使用服务。

共享抽屉实例的服务

@Injectable({
    providedIn: 'root'
})
export class DrawerService {
    private matDrawer: MatDrawer;

    setDrawer(drawer: MatDrawer) {
        this.matDrawer = drawer;
    }

    toggle() {
         this.matDrawer.toggle();
    }
}

包含抽屉垫的组件

export class WithDrawerComponent implements OnInit {
  @ViewChild(MatDrawer) matDrawer: MatDrawer;
  constructor(private drawerService: DrawerService) {

  }

  ngOnInit() {
    this.drawerService.setDrawer(this.matDrawer);
  }
}

使用按钮激活切换的组件

export class WithButtonComponent implements OnInit {
  constructor(private drawerService: DrawerService) {
  }

  toggleDrawer() {
    this.drawerService.toggle();
  }
}

希望对您有帮助

答案 1 :(得分:0)

要从另一个组件切换辅助导航,您需要:

  1. 属性装饰器@ViewChild。
  2. 完成此功能的服务。

例如,假设您有一个标头组件,它管理所有标头,还有几个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

在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);
  }
}

对于另一边导航,您将重复相同的过程...

AppComponent

在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>