Take this code for example…
component.html
<mat-toolbar (click)=“potentialNav($event)”>
<mat-toolbar-row>
<button mat-icon-button matRipple>
<mat-icon fontIcon=“chevron_left”></mat-icon>
</button>
<span>Current View Title</span>
<span style=“flex: 1;”></span>
<button mat-icon-button matRipple>
<mat-icon fontIcon=“close”></mat-icon>
</button>
</mat-toolbar-row>
</mat-toolbar>
<router-outlet></router-outlet>
Renders a simple primary app header bar that more or less looks like this…
———————————————————————————————————————
< Current View Title X
———————————————————————————————————————
Now in the component logic, we have something like this…
component.ts
public potentialNav(event: Event): void {
// Determine button used, and act accordingly
const button: string = event….something? // between event and target, if button clicked, read the `fontIcon` value off button’s <mat-icon>
switch (button) {
case “chevron_left”:
this.navigateBack();
break;
case “close”:
this.cancel();
break;
default:
…
break;
}
}
private navigateBack(): void {
this.router.navigate([“…”]);
}
private cancel(): void {
this.router.navigate([“…”]);
}
Now the issue is this, that this primary app header bar is extremely dynamic, differing between different screens/views
As it is now, it exists in AppComponent and in app.component.html outside of the <router-outlet>
So, there are going to be a variety of different buttons rendered (or not), at any given time, from point to point
You may be thinking to yourself, “why don’t you just do this?”…
<button mat-icon-button matRipple (click)=“navigateBack()”>
<mat-icon fontIcon=“chevron_left”></mat-icon>
</button>
public navigateBack(): void {
this.router.navigate([“…”]);
}
But I feel that one event listener and delegation here is probably the simplest/easiest way of handling such dynamic complexities, because the primary AppComponent is not always going to have access to all of the relevant data and/or services it needs at a given time, to actually in fact be capable of handling the action itself. For example, what if it’s a form upload/submit button that lives in a child component? Makes a lot more sense for that child component to have it’s own specific onSubmit() and upload() methods, then individually import any relevant and necessary services required to. Are these methods function properly within itself only, rather than bog down the AppComponent
What such a child component WOULD need to know though, is whether a given user action within the app main header, should trigger it’s own internal logic, such as if it’s own private this.upload() or this.cancel() needs to run
To accomplish this, I’m thinking of creating a service that AppComponent simply writes to, and then any components interested in specific navigation events or application commands from the main app header would subscribe() to
In this case I’d modify AppComponent to remove any complex if or switch statements, simply sending off any buttons used like this
public potentialNav(event: Event): void {
const button = … // again, still need to read `fontIcon` attribute somehow
if (button) this.service.respondTo(button);
}
and then move any of that more complex if/switch logic into the new service, which might look like this…
public requested$ = new Subject<string>();
public respondTo(action: string): void {
// complex if/switch logic moved here
// once processed/verified
this.requested$.next(action);
}
Angular specific object/class/implementation, and varies WILDLY outside of the traditional HMTL DOM Element