Reputation: 156
I am trying to sidenav toggle from another component, however when the .toggle() function gets called from my parent component it throws this error:
AppComponent.html:1 ERROR TypeError: this.sidenav.toggle is not a function at AppComponent.webpackJsonp.176.AppComponent.toggleNav (app.component.ts:25)
here is the code: app.component.ts
import { Component, ViewChild } from '@angular/core';
import { MaterialModule } from '@angular/material';
import { NavComponent } from './nav/nav.component';
import { SidebarComponent } from './sidebar/sidebar.component';
import { FooterComponent } from './footer/footer.component';
import { MdSidenav } from '@angular/material';
@Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent{
title = 'CRS Management App';
@ViewChild('sidenav') sidenav:MdSidenav;
toggleNav(){
this.sidenav.toggle();
}
}
app.component.html:
<app-nav #navbar (nav)="toggleNav()"></app-nav>
<app-sidebar #sidenav></app-sidebar>
<app-footer></app-footer>
the (nav) is emitted from the app-nav component.
sidebar.component.ts:
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss']
})
export class SidebarComponent {
title = 'CRS';
constructor() { }
}
sidebar.component.html:
<md-sidenav-container class="container">
<!--SIDEBAR -->
<md-sidenav #sidebar class="sidebar" mode="over" opened="true">
<!-- MENU https://material.angular.io/components/component/list -->
<div class="nav-links">
<md-nav-list> <!--TODO Links -->
<a md-list-item href="/one"> Option </a> <!--TODO Icon -->
<a md-list-item href="/two"> Option </a> <!--TODO Icon-->
<a md-list-item href="/three"> Option </a> <!--TODO Icon-->
<span class="flex"></span><!--TODO Divider-->
<a md-list-item href="/four"> _______ </a> <!--TODO Icon-->
<a md-list-item href="/five"> Option </a> <!--TODO Icon -->
<a md-list-item href="/six"> Option </a> <!--TODO Icon-->
<a md-list-item href="/seven"> Option </a> <!--TODO Icon-->
<a md-list-item href="/eight"> Option </a> <!--TODO Icon-->
</md-nav-list>
<!-- SETTINGS -->
<!--TODO link to settings -->
<!--TODO Convert to md-list-item -->
<button md-button class="md-icon-button" aria-label="Settings">
Settings<md-icon>settings</md-icon>
</button>
<!-- SETTINGS END -->
</div>
</md-sidenav>
<!-- SIDEBAR ENDS -->
<router-outlet></router-outlet>
</md-sidenav-container>
I have tried using AfterViewInit, it throws:
ERROR TypeError: this.sideNav.toggle is not a function at AppComponent.webpackJsonp.176.AppComponent.toggleNav (http://127.0.0.1:4200/main.bundle.js:171:22)
Upvotes: 5
Views: 8837
Reputation: 11525
The template ref #sidenav on the AppComponent refers to the SidebarComponent which does not have a toggle function.
You could add one to it which then calls the sidenav.toggle() and then you could call that from the AppComponent.
sidebar.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatSidenav} from '@angular/material';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
title = 'CRS';
@ViewChild('sidenav') sidenav: MatSidenav;
constructor() { }
ngOnInit() {
}
toggle() {
this.sidenav.toggle();
}
}
sidebar.component.html
<md-sidenav-container class="container">
<md-sidenav #sidenav class="sidebar" mode="over" opened="true">
...
</md-sidenav>
</md-sidenav-container>
Upvotes: 9
Reputation: 397
In my case I didn't include MatSidenavModule in my component module imports list. That solved the problem. It looks like some other Material module has indirectly imports the SidenaveModule, that is the reason we didn't get the usual error when we don't import the module in our component.
Upvotes: 1
Reputation: 2655
Try to use ngAfterViewInit
callback, here's a good example.
Upvotes: 0