title: Controling the angular material mat-drawer from another component
body: <p>I have two components, the AppNav component and the Machines component. The AppNav component has the toolbar and sidenav. I have also placed a filter button on the toolbar of the AppNav. In the Machines Component there's a mat-drawer which needs to be toggled after clicking on the filter button in the toolbar of the AppNav. The problem is I don't know how to make the two communicate. The Machines component is not a direct child of the AppNav component since I'm loading the other components (Machines, etc) via router-outlet placed in the sidenav-content of the AppNav.</p>
  
  <p>Look at the components from below:</p>
  
  <p>The DrawerService (that I thought of creating to maybe ease my frustration)</p>
  
  <pre><code>import { Injectable } from '@angular/core';
  import { MatDrawer } from '@angular/material';
  
  @Injectable({
      providedIn: 'root'
  })
  export class DrawerService {
      private drawer: MatDrawer;
  
      /**
       * setDrawer
       */
      public setDrawer(flyout: MatDrawer) {
          this.drawer = flyout;
      }
  
      /**
       * open
       */
      public open() {
          return this.drawer.open();
      }
  
      /**
       * close
       */
      public close() {
          return this.drawer.close();
      }
  
      /**
       * toggle
       */
      public toggle(): void {
          this.drawer.toggle();
      }
  }
  </code></pre>
  
  <p>The Machines component (machines.component.ts)</p>
  
  <pre><code>import { Component, OnInit } from '@angular/core';
  
  @Component({
      selector: 'app-machines',
      templateUrl: './machines.component.html',
      styleUrls: ['./machines.component.sass']
  })
  export class Machines implements OnInit {
  
      constructor() { }
  
      ngOnInit() {
      }
  
  }
  </code></pre>
  
  <p>The Machines html (machines.component.html) </p>
  
  <pre><code>&lt;mat-drawer-container
      fxFlexFill&gt;
      &lt;mat-drawer 
          mode="side"
          opened
          position="end"
          #flyout
          class="mat-elevation-z3"
          [style.width]="'200px'"&gt;
  
          &lt;mat-toolbar&gt;
              &lt;span&gt;Filter&lt;/span&gt;
  
              &lt;span fxFlex&gt;&lt;/span&gt;
  
              &lt;mat-icon 
                  svgIcon="close"
                  (click)="flyout.toggle()"&gt;&lt;/mat-icon&gt;
          &lt;/mat-toolbar&gt;
  
          &lt;mat-list&gt;
              &lt;mat-list-item&gt;01&lt;/mat-list-item&gt;
              &lt;mat-list-item&gt;02&lt;/mat-list-item&gt;
              &lt;mat-list-item&gt;03&lt;/mat-list-item&gt;
              &lt;mat-list-item&gt;04&lt;/mat-list-item&gt;
          &lt;/mat-list&gt;
      &lt;/mat-drawer&gt;
      &lt;mat-drawer-content&gt;
          &lt;div&gt;
              Lorem ipsum, dolor sit amet consectetur adipisicing elit. Saepe, id assumenda ratione quaerat at itaque dolorem sit ipsam, modi nam voluptatem nisi expedita quis possimus ea a sed neque? Iure!
          &lt;/div&gt;
      &lt;/mat-drawer-content&gt;
  &lt;/mat-drawer-container&gt;
  </code></pre>
  
  <p>The AppNav component (app-nav.component.ts)</p>
  
  <pre><code>import { Component, ViewChild, ViewChildren } from '@angular/core';
  import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
  import { Observable } from 'rxjs';
  import { map } from 'rxjs/operators';
  import { ThemeService } from '../services/theme.service';
  import { DrawerService } from '../services/drawer.service';
  import { MatDrawer } from '@angular/material';
  
  @Component({
      selector: 'app-nav',
      templateUrl: './nav.component.html',
      styleUrls: ['./nav.component.sass']
  })
  export class AppNav {
      yearTodate: number = new Date().getFullYear();
      isDarkTheme: Observable&lt;boolean&gt;;
      links: Array&lt;Object&gt;;
  
      isHandset$: Observable&lt;boolean&gt; = this.breakpointObserver.observe(Breakpoints.Handset)
      .pipe(
          map(result =&gt; result.matches)
      );
  
      @ViewChildren('flyout') public flyout: MatDrawer;
  
      constructor(
          private breakpointObserver: BreakpointObserver,
          private drawerService: DrawerService,
          private themeService: ThemeService) {}
  
      ngOnInit() {
          this.isDarkTheme = this.themeService.isDarkTheme;
          this.links = this.linksArray;
          this.drawerService.setDrawer(this.flyout);
      }
  
      toggleDarkTheme(checked: boolean) {
          this.themeService.setDarkTheme(checked);
      }
  
      toggleFlyout () {
          this.drawerService.toggle();
      }
  
      linksArray = [
  
          {
              route: "/dashboard",
              icon: "ballot",
              name: "Dashboard"
          },
  
          {
              route: "/vehicles",
              icon: "car",
              name: "Vehicles"
          }
      ]
  
  }
  </code></pre>
  
  <p>The AppNav html (app-nav.component.html)</p>
  
  <pre><code>&lt;div
      [ngClass]="{'dark-theme': isDarkTheme | async}"
      fxLayout="column" 
      fxLayoutAlign="center center"
      fxFlexFill
      class="mat-app-background"
      style="position: relative"&gt;
      &lt;mat-sidenav-container class="sidenav-container"&gt;
          &lt;mat-sidenav
              #drawer
              class="sidenav mat-elevation-z3"
              fixedInViewport="true"
              [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
              [mode]="(isHandset$ | async) ? 'over' : 'side'"
              [opened]="!(isHandset$ | async)"
              fxLayout="column"&gt;
  
              &lt;mat-nav-list&gt;
                  &lt;a 
                      mat-list-item
                      routerLink="{{link.route}}"
                      *ngFor="let link of links"&gt;
                      &lt;mat-icon svgIcon="{{link.icon}}"&gt;&lt;/mat-icon&gt;
                      &lt;span fxFlex="5"&gt;&lt;/span&gt;
                      &lt;span&gt;{{link.name}}&lt;/span&gt; 
                  &lt;/a&gt;
              &lt;/mat-nav-list&gt;
  
              &lt;span fxFlex&gt;&lt;/span&gt;
  
              &lt;mat-nav-list&gt;
                  &lt;a 
                      mat-list-item
                      routerLink="/login"&gt;
                      &lt;mat-icon svgIcon="login"&gt;&lt;/mat-icon&gt;
                      &lt;span fxFlex="5"&gt;&lt;/span&gt;
                      &lt;span&gt;Login&lt;/span&gt; 
                  &lt;/a&gt;
              &lt;/mat-nav-list&gt;
  
              &lt;mat-divider&gt;&lt;/mat-divider&gt;
  
              &lt;small 
                  style="padding: 16px"&gt;
                  &amp;copy;{{yearTodate}} MotionPlus
              &lt;/small&gt;
          &lt;/mat-sidenav&gt;
  
          &lt;mat-sidenav-content
              fxLayout="column"&gt;
              &lt;mat-toolbar 
                  color="primary"&gt;
                  &lt;button
                      type="button"
                      aria-label="Toggle sidenav"
                      mat-icon-button
                      (click)="drawer.toggle()"
                      *ngIf="isHandset$ | async"&gt;
                      &lt;mat-icon 
                          aria-label="Side nav toggle icon"
                          svgIcon="menu"&gt;
                          &lt;!-- menu --&gt;
                      &lt;/mat-icon&gt;
                  &lt;/button&gt;
  
                  &lt;span&gt;MotionPlus&lt;/span&gt;
  
                  &lt;span fxFlex&gt;&lt;/span&gt;
  
                  &lt;button 
                      mat-icon-button
                      (click)="toggleFlyout()"&gt;
                      &lt;mat-icon svgIcon="filter-variant"&gt;&lt;/mat-icon&gt;
                  &lt;/button&gt;
  
                  &lt;button 
                      mat-icon-button
                      [matMenuTriggerFor]="bucket"&gt;
                      &lt;mat-icon
                          svgIcon="format-color-fill"&gt;&lt;/mat-icon&gt;
                  &lt;/button&gt;
  
                  &lt;mat-menu
                      #bucket="matMenu"&gt;
                      &lt;button 
                          mat-menu-item
                          (click)="toggleDarkTheme(true)"
                          fxLayout="column"
                          fxLayoutAlign="center center"&gt;
                          &lt;span
                              style="
                                  background: purple; 
                                  width: 42px; 
                                  height: 42px; 
                                  border-radius: 50%"&gt;
                          &lt;/span&gt;
                      &lt;/button&gt;
  
                      &lt;button 
                          mat-menu-item
                          (click)="toggleDarkTheme(false)"
                          fxLayout="column"
                          fxLayoutAlign="center center"&gt;
                          &lt;span
                              style="
                                  background: yellow; 
                                  width: 42px; 
                                  height: 42px; 
                                  border-radius: 50%"&gt;
                          &lt;/span&gt;
                      &lt;/button&gt;
                  &lt;/mat-menu&gt;
              &lt;/mat-toolbar&gt;
              &lt;!-- Add Content Here --&gt;
              &lt;div
                  style="padding: 0 24px;"
                  fxFlex&gt;
                  &lt;router-outlet&gt;&lt;/router-outlet&gt;
              &lt;/div&gt;
          &lt;/mat-sidenav-content&gt;
      &lt;/mat-sidenav-container&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Point me in the right direction on how I can achieve this. I want to control the opening and closing of the mat-drawer that is in the Machines component (which loads dynamically via router-outlet) from the AppNav component. </p>