The app.component.ts
is the entry point of my Angular 2 app. It holds two components: a header and a sidenav.
@Component({
selector: 'app-root',
template: `
<app-header></app-header>
<app-sidenav></app-sidenav>
`
})
export class AppComponent { }
Here's what I want to achieve: Inside the <app-header>
component I have a (menu) button, that should trigger the opening of the <app-sidenav>
component.
In other words, a click event on the button in the <app-header>
should trigger the open()
method inside the <app-sidenav>
component.
header.component.ts:
@Component({
selector: 'app-header',
template: `
<button (click)="onSidenavOpen()">Menu</button>
`
})
export class HeaderComponent {
constructor() { }
onSidenavOpen() {
// trigger the opening of the <app-sidenav> component
}
}
sidebar.component.ts:
@Component({
selector: 'app-sidenav',
template: `
<md-sidenav #sidenav>
// bla bla, sidebar
</md-sidenav>
`
})
export class SidenavComponent {
constructor() { }
open(sidenav) {
sidenav.open();
}
close(sidenav) {
sidenav.close();
}
}
I read the component interaction section in the Angular 2 docs, but I am struggling to find the best approach to communicate between these two components. The general intention I have is to encapsulate as much logic as possible for each component.
How would you approach my use-case? Would you create an intermediate service? Please share an example.
You can use a service to allow two separate components to talk to each other. In the example below, the HeaderComponent
pushes a value to an exposed Observable
with the toggleSideNav
method of the SidebarService
. The SidenavComponent
subscribes to this Observable
on its initial load and will respond to a new value being pushed through.
SidebarService:
import { Injectable } from "@angular/core"
import { Observable, Subject } from "rxjs/Rx";
@Injectable()
export class SidebarService {
private sidenavOpenSubject : Subject<boolean>;
constructor() {
this.sidenavOpenSubject = new Subject<boolean>();
}
toggleSideNav(opening: boolean): void {
this.sidenavOpenSubject.next(opening);
}
onSideNavToggle(): Observable<boolean> {
return this.sidenavOpenSubject;
}
}
HeaderComponent:
@Component({
selector: 'app-header',
template: `
<button (click)="onSidenavOpen()">Menu</button>
`
})
export class HeaderComponent {
constructor(private sidebarService: SidebarService) { }
onSidenavOpen() {
this.sidebarService.toggleSideNav(true);
}
}
SidebarComponent:
@Component({
selector: 'app-sidenav',
template: `
<md-sidenav #sidenav>
// bla bla, sidebar
</md-sidenav>
`
})
export class SidenavComponent implements OnInit {
constructor(private sidebarService: SidebarService) { }
ngOnInit(): void {
this.sidebarService.onSideNavToggle().subscribe(
(opening) => {
if (opening) {
//Logic to open the sidenav here
} else {
//Logic to close the sidenav here
}
}
);
}
open(sidenav) {
sidenav.open();
}
close(sidenav) {
sidenav.close();
}
}
The SidebarService
needs to be registered in a suitable module (e.g. your AppModule
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With