🐟

[Angular][Material] Sidenavでナビゲーションバーを設置

2022/12/21に公開

Angular Materialには、折りたたみ可能なサイドコンテンツ(多くの場合ナビゲーションですが、どんなコンテンツでも構いません)を主要コンテンツの横に追加するためのコンポーネントが2セットあります。これらはsidenavコンポーネントとdrawerコンポーネントです。

import {MatSidenavModule} from '@angular/material/sidenav';

要素

<mat-drawer-container>でナビゲーションを展開する領域を囲います。

ナビゲーション本体は<mat-drawer>で囲います。

<mat-drawer-container>
<mat-drawer>

同一コンポーネント内で開閉ボタンを設置

ナビゲーションと開閉ボタンを同一コンポーネントに設置する場合です。

html
mat-sidenav-module\mat-sidenav-module.component.html

<mat-drawer-container class="sidenavContainer" autosize>

  <mat-drawer #drawer class="drawer" mode="side">
    <p>ぽち</p>
    <img
      src="https://material.angular.io/assets/img/examples/shiba2.jpg"
      alt="Photo of a Shiba Inu"
      height="200px"
      width="auto"
    >

  </mat-drawer>

  <div class="content">
    <p>ParentComponent!</p>
    <button mat-raised-button color="primary" (click)="drawer.toggle()">Toggle Sidenav</button>
  </div>

</mat-drawer-container>

component
mat-sidenav-module\mat-sidenav-module.component.ts

import { Component, OnInit} from '@angular/core';

@Component({
  selector: 'app-mat-sidenav-module',
  templateUrl: './mat-sidenav-module.component.html',
  styleUrls: ['./mat-sidenav-module.component.css']
})
export class MatSidenavModuleComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

css
mat-sidenav-module\mat-sidenav-module.component.css

.sidenavContainer {
  height: 100%;
  border: 1px solid rgba(0, 0, 0, 0.5);
}
.drawer {
  padding: 10px;
}

.content {
  display: flex;
  flex-direction: column;
  height: 50%;
  align-items: center;
}

開閉ボタンのイベントは上記のように直接htmlでdrawer.toggle()のように指定してもOK。

コンポーネントから下記のようにクリックインベントで指定してもOK。

@ViewChild('drawer') drawer!: any;

onClick() {
	this.drawer.toggle();
}

子コンポーネントから開閉ボタンを設置

親コンポーネントのナビゲーションを子コンポーネントから開閉する場合です。

親html
mat-sidenav-module\mat-sidenav-module.component.html

<mat-drawer-container class="sidenavContainer" autosize>

  <mat-drawer #drawer class="drawer" mode="side">
    <p>ぽち</p>
    <img
      src="https://material.angular.io/assets/img/examples/shiba2.jpg"
      alt="Photo of a Shiba Inu"
      height="200px"
      width="auto"
    >

  </mat-drawer>

  <div class="content">
    <p>ParentComponent!</p>
    <button mat-raised-button color="primary" (click)="drawer.toggle()">Toggle Sidenav</button>
  </div>

  **<app-sidenav-child [drawer]="drawer"></app-sidenav-child>**

</mat-drawer-container>
  • 子コンポーネントにdrawerを渡します。

親component
mat-sidenav-module\mat-sidenav-module.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';

@Component({
  selector: 'app-mat-sidenav-module',
  templateUrl: './mat-sidenav-module.component.html',
  styleUrls: ['./mat-sidenav-module.component.css']
})
export class MatSidenavModuleComponent implements OnInit {

  @ViewChild('drawer') drawer!: MatSidenav;

  constructor() { }

  ngOnInit(): void {
  }

}
  • 子コンポーネントに渡すため、viewChildでテンプレートのdrawer要素を取得します

子html
mat-sidenav-module\sidenav-child\sidenav-child.component.html

<div class="childContent">
  <p>ChildComponent!</p>
  <button mat-stroked-button color="accent" (click)="onClick()">Toggle Sidenav</button>
</div>

子component
mat-sidenav-module\sidenav-child\sidenav-child.component.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-sidenav-child',
  templateUrl: './sidenav-child.component.html',
  styleUrls: ['./sidenav-child.component.css']
})
export class SidenavChildComponent implements OnInit {

  @Input()
  drawer: any;

  constructor() { }

  ngOnInit(): void {
  }

  onClick() {
    this.drawer.toggle();
  }
}
  • Input()で親コンポーネントからdrawerを受け取ります
  • toggle()メソッドで開閉します

css
mat-sidenav-module\sidenav-child\sidenav-child.component.css

.childContent {
  display: flex;
  flex-direction: column;
  height: 50%;
  align-items: center;
  border: 1px solid rgba(0, 0, 0, 0.5);
}

メソッド

ナビゲーションを開く

open()

ナビゲーションを閉じる

close()

ナビゲーションの開閉トグル

toggle()

参考

https://material.angular.io/components/sidenav/api

Discussion