Normally, in Angular 2, one would listen to an event via the following syntax:
<my-elem (customEvent)="customEventProcessor"></my-elem>
But when I use a router, that host - <my-elem>
- does not exist in any template. Instead, there's a <router-outlet>
, and my component is loaded upon navigation. Thus, the crux of my problem is, How can I force my host to listen to my custom event without relying on a template?
Suppose I have some element list-view
, which is a child of my root component. list-view
listens for a custom event via the normal syntax:
<list-view (customEvent)="customEventProcessor()"></list-view>
Just for completeness, the list-view
component that emits the event also has a predictable structure:
<button (click)="onDetailsClick(propertyOfInterest)">Click here</button>
The list-view
sends the event up to the parent via observation.
class ListView {
...
public onDetailsClick(property: string): void {
this.customEvent.next({ value: property });
}
}
and that event triggers the customEventProcessor()
function. So far so good. However, when I use a router to control whether list-view
is present, I cannot (to my knowledge) insert a command to monitor some event.
I am not sure what the best approach is to handle this case.
@HostListener is Angular's decorator method that's used for listening to DOM events on the host element of both component and attribute directives.
The $event object often contains information the method needs, such as a user's name or an image URL. The target event determines the shape of the $event object. If the target event is a native DOM element event, then $event is a DOM event object, with properties such as target and target.
Events are handled in Angular using the following special syntax. Bind the target event name within parentheses on the left of an equal sign, and event handler method or statement on the right. Above, (click) binds the button click event and onShow() statement calls the onShow() method of a component.
The event you passed through $event is a DOM event, therefore you can use the EventName as the type. The MouseEvent interface represents events that occur due to the user interacting with a pointing device (such as a mouse). Common events using this interface include click, dblclick, mouseup, mousedown.
This problem isn't resolved yet (see this github issue). Here is one of the possible solutions at this moment (see this plunk):
@Component({
selector: 'my-app',
directives: [RouterOutlet, RouterLink],
template: `
<h1>{{ message }}</h1>
<a [router-link]="['./MyElem1']">MyElem1</a>
<a [router-link]="['./MyElem2']">MyElem2</a>
<router-outlet></router-outlet>
`
})
@RouteConfig([
{ path: '/', redirectTo: '/my-elem1' },
{ path: '/my-elem1', name: 'MyElem1', component: MyElem1 },
{ path: '/my-elem2', name: 'MyElem2', component: MyElem2 },
])
export class App {
message: string = 'Click on the button';
@ViewChild(MyElem1) myElem1: MyElem1;
@ViewChild(MyElem2) myElem2: MyElem2;
constructor(router: Router) {
let subs = null;
router.subscribe(() => {
if (subs) { subs.unsubscribe(); subs = null; }
if (this.myElem1) {
subs = this.myElem1.customEvent1.subscribe(m=>this.processCustomEvent(m));
}
if (this.myElem2) {
subs = this.myElem2.customEvent2.subscribe(m=>this.processCustomEvent(m));
}
});
}
processCustomEvent(message) { this.message = message }
}
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