Often, BeetleJuice's solution works best: placing cross-component functionality into services.
However, there are times when you have highly cohesive components that you want to link directly in the parent component's HTML template.
In such cases, using a service might be excessive. Fortunately, you can utilize the template reference variables (#var)
Imagine you have a popup component:
// import...
@Component({
selector: 'my-popup',
template: '<div *ngIf="visible"><ng-content></ng-content></div>'
})
export class MyPopupComponent {
public visible: boolean = false;
public toggle() {
this.visible = !this.visible;
}
}
And a toggle component that triggers the popup component to toggle:
// import...
@Component({
selector: 'my-popup-toggle',
template: '<button (click)="popup?.toggle()"><ng-content></ng-content></button>'
})
export class MyPopupToggleComponent {
@Input('for') popup: MyPopupComponent;
}
Connecting components across the HTML is straightforward:
<div>
<my-popup #popup1>Good popup</my-popup>
<my-popup #popup2>Better popup</my-popup>
<my-popup #popup3>Best popup</my-popup>
</div>
<div>
<my-popup-toggle [for]="popup1">Toggle the good</my-popup-toggle>
<my-popup-toggle [for]="popup2">Toggle the better</my-popup-toggle>
<my-popup-toggle [for]="popup3">Toggle the best</my-popup-toggle>
<my-popup-toggle [for]="popup3">Toggle the best with another button</my-popup-toggle>
</div>
In simple scenarios, you can also do something like this:
<div>
<my-popup #popup4>Best popup II</my-popup>
</div>
<div>
<button (click)="popup4.show()">Toggle the best II</button>
</div>
If needed, you can access the template reference variable from the parent component as well:
// import...
@Component({
selector: 'my-parent-comonent',
template: `
...<my-popup #popup5>Best popup III</my-popup>...
...<my-popup #popup6>Best popup IV</my-popup>...
`
})
export class MyParentComponent {
@ViewChild('popup5') popup5: MyPopupComponent;
@ViewChild('popup5') popup5: MyPopupComponent;
showPopup5() { this.popup5.show(); }
showPopup6() { this.popup6.show(); }
}