Angularの勉強中です。
ハンバーガーメニューのように、ボタンで表示できるサイドメニューが作りたいです。
色々調べた結果Angular Materialのsidenavを使おうと思っています。
今回はsidenavをコンポーネントとして実装し、ディレクトリ構造は以下のようにしています。
(ゆくゆくはサイドメニューの中をDBから取得した情報をもとに表示したい為、sidenavというserviceを設けていますが現在は使用していません)
app
├ component
│ ├common
│ │ ├ header
│ │ │ ├header.component.html
│ │ │ ├header.component.scss
│ │ │ ├header.component.spec.ts
│ │ │ └header.component.ts
│ │ ├ sidenav
│ │ │ ├sidenav.component.html
│ │ │ ├sidenav.component.scss
│ │ │ ├sidenav.component.spec.ts
│ │ │ └sidenav.component.ts
├ service
│ ├common
│ │ ├ sidenav
│ │ │ ├sidenav.service.spec.ts
│ │ │ └sidenav.service.ts
├ utils
│ ├material
│ │ └material.module.ts
├ app-routing.module.ts
├ app.component.html
├ app.component.scss
├ app.component.spec.ts
├ app.component.ts
├ app.module.ts
└ etc...
現在のソースコードは以下の通りです。
【header.component.html】
header <p><button mat-button (click)="sidenav.toggle()">sidenav.toggle()</button></p>
【header.component.ts】
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.scss'] }) export class HeaderComponent implements OnInit { constructor() { } ngOnInit() { } }
【sidenav.component.html】
<mat-nav-list> ・メニュー1<br> ・メニュー2 </mat-nav-list>
【sidenav.component.ts】
import { Component, OnInit, Output, EventEmitter } from '@angular/core'; import { SidenavService } from 'src/app/service/common/sidenav/sidenav.service'; // import { AvailableMenuListDto } from 'src/app/entity/dto/available-menu-list-dto'; @Component({ selector: 'app-sidenav', templateUrl: './sidenav.component.html', styleUrls: ['./sidenav.component.scss'] }) export class SidenavComponent implements OnInit { @Output() sidenavClose = new EventEmitter(); constructor( private sidenavService: SidenavService, ) { } ngOnInit() { // メニューを取得する。 // this.getAvailableMenu(); } /** * メニュー選択後に親コンポーネントに対してクローズイベントを発生する。 */ public onSidenavClose() { this.sidenavClose.emit(); } }
【material.module.ts】
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; // Angular Materialで使用するモジュールをここに追加 import { MatSidenavModule } from '@angular/material/sidenav'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatMenuModule } from '@angular/material/menu'; import { MatListModule } from '@angular/material/list'; import { MatIconModule } from '@angular/material/icon'; @NgModule({ declarations: [], imports: [ CommonModule, MatSidenavModule, MatToolbarModule, MatMenuModule, MatListModule, MatIconModule, ], exports: [ MatSidenavModule, MatToolbarModule, MatMenuModule, MatListModule, MatIconModule, ] }) export class MaterialModule { }
【app-routing.module.ts】
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
【app.component.html】
<mat-sidenav-container> <!-- sidenav --> <mat-sidenav #sidenav mode="side"> <app-sidenav (sidenavClose)="sidenav.close()"></app-sidenav> </mat-sidenav> <!-- main content --> <mat-sidenav-content> <app-header></app-header> </mat-sidenav-content> </mat-sidenav-container>
【app.component.ts】
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'AngularTest'; }
【app.module.ts】
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HeaderComponent } from './component/common/header/header.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MaterialModule } from 'src/app/utils/material/material.module'; import { SidenavComponent } from './component/common/sidenav/sidenav.component'; @NgModule({ declarations: [ AppComponent, HeaderComponent, SidenavComponent ], imports: [ BrowserModule, AppRoutingModule, BrowserAnimationsModule, MaterialModule, ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
現在はheaderの中に
<p><button mat-button (click)="sidenav.toggle()">sidenav.toggle()</button></p> を入れており、これをクリックすると Cannot read property 'toggle' of undefined というエラーになってしまいます。ただ、このボタンを【app.component.html】にそのまま書くとうまく動きます。
ボタンをHeaderに入れても動くようにするにはどうすればよいのでしょうか。
あなたの回答
tips
プレビュー