简体   繁体   中英

Target a template reference variable from another component in Angular 2

Is there a way to target a template reference variable in another component?
I would like to trigger the side nav by creating an event that calls the sidenav's open function through the TRV sidenav .

app.component.html

<md-sidenav-layout>

    <md-sidenav #sidenav (open)="mybutton.focus()">
      Start Sidenav.
      <br>
      <button md-button #mybutton (click)="sidenav.close()">Close</button>
    </md-sidenav>

    <top-bar></top-bar>

    <main class="main" (openNav)="sidenav.open()">
      <router-outlet></router-outlet>
    </main>

</md-sidenav-layout>

topbar.component.html

<md-toolbar color="primary">
  <button class="app-icon-button" (click)="openSideNav()">
    <i class="material-icons app-toolbar-menu">menu</i>
  </button>
  <span [routerLink]="['']">Home</span>
  <span [routerLink]="['test']"  class="navlink">Test</span>
  <span class="navlink" (click)="signout()">signout</span>
</md-toolbar>

topbar.component.ts

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
@Component({
  selector: 'top-bar',
  templateUrl: './topbar.component.html',
  styleUrls: ['./topbar.component.css']
})
export class TopbarComponent implements OnInit {
  constructor() { }
  @Output() openNav = new EventEmitter();
  openSideNav(){
    console.log(this.openNav.emit());
    this.openNav.emit();
  }
  ngOnInit() {
  }
}

Is it possible for me to target the template variable in the app component from the topbar directive?

I see a couple options.

One, you can create a service that holds the sidenav instance. You can set the sidenav from the app component.

class SidenavService {
  private _sidenav: MdSidenav;

  set sidenav(nav: MdSidenav) {
    this._sidenav = nav; 
  } 

  open() {
    if (this._sidenav) this.sidenav.open();
  }

  close() {
    if (this._sidenav) this._sidenav.close();
  }
}

And in your app controller

class AppComponent implements AfterViewInit {
  @ViewChild(MdSidenav) sidenav: MdSidenav;

  constructor(private sidenavService: SidenavService) {}

  ngAfterViewInit() {
    this.sidenavService.sidenav = this.sidenav;
  }
}

Then you can inject the SidenavService into whatever other component where you want to have access to it.

The other options is to simply have the sidenav as an input to the topbar.

<topbar [sidenav]="sidenav"></topbar>

class TopbarComponent {
  @Input() sidenav: MdSidenav;
}

I personally don't like the second option, as I don't like exposing the sidenav unnecessarily. I'd rather just use the service and control what others can do with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM