patterntypescriptangularCritical
Dynamically add event listener
Viewed 0 times
addlistenereventdynamically
Problem
I am just starting to mess around with Angular 2 and I wonder if anyone can tell me the best way to dynamically add and remove event listeners from elements.
I have a component set up. When a certain element in the template is clicked I want to add a listener for
I kind of got this working just using plain Javascript to grab the elements and then calling the standard
I have a component set up. When a certain element in the template is clicked I want to add a listener for
mousemove to another element of the same template. I then want to remove this listener when a third element is clicked.I kind of got this working just using plain Javascript to grab the elements and then calling the standard
addEventListener() but I wondered if there was a more "Angular2.0" way of doing this that I should be looking into.Solution
Renderer has been deprecated in Angular 4.0.0-rc.1, read the update below
The angular2 way is to use
For example, if you want to add a click event to a Component, you have to use Renderer and ElementRef (this gives you as well the option to use ViewChild, or anything that retrieves the
You can use
Note that since beta.2 both
So to remove the listener we added dynamically we must assign
Here's a plnkr with an example working. The example contains the usage of
Using RendererV2 with Angular 4.0.0-rc.1+ (Renderer2 since 4.0.0-rc.3)
-
25/02/2017:
-
10/03/2017:
For reference, I'm copy & pasting the source code of the DOM Renderer implementation since it may change (yes, it's angular!).
As you can see, now it verifies if we're passing a string (document, body or window), in which case it will use an internal
To remove the listener it's the same as it was with
Example
plnkr with Angular 4.0.0-rc.1 using RendererV2
plnkr with Angular 4.0.0-rc.3 using Renderer2
The angular2 way is to use
listen or listenGlobal from RendererFor example, if you want to add a click event to a Component, you have to use Renderer and ElementRef (this gives you as well the option to use ViewChild, or anything that retrieves the
nativeElement)constructor(elementRef: ElementRef, renderer: Renderer) {
// Listen to click events in the component
renderer.listen(elementRef.nativeElement, 'click', (event) => {
// Do something with 'event'
})
);
You can use
listenGlobal that will give you access to document, body, etc.renderer.listenGlobal('document', 'click', (event) => {
// Do something with 'event'
});
Note that since beta.2 both
listen and listenGlobal return a function to remove the listener (see breaking changes section from changelog for beta.2). This is to avoid memory leaks in big applications (see #6686).So to remove the listener we added dynamically we must assign
listen or listenGlobal to a variable that will hold the function returned, and then we execute it.// listenFunc will hold the function returned by "renderer.listen"
listenFunc: Function;
// globalListenFunc will hold the function returned by "renderer.listenGlobal"
globalListenFunc: Function;
constructor(elementRef: ElementRef, renderer: Renderer) {
// We cache the function "listen" returns
this.listenFunc = renderer.listen(elementRef.nativeElement, 'click', (event) => {
// Do something with 'event'
});
// We cache the function "listenGlobal" returns
this.globalListenFunc = renderer.listenGlobal('document', 'click', (event) => {
// Do something with 'event'
});
}
ngOnDestroy() {
// We execute both functions to remove the respectives listeners
// Removes "listen" listener
this.listenFunc();
// Removs "listenGlobal" listener
this.globalListenFunc();
}
Here's a plnkr with an example working. The example contains the usage of
listen and listenGlobal.Using RendererV2 with Angular 4.0.0-rc.1+ (Renderer2 since 4.0.0-rc.3)
-
25/02/2017:
Renderer has been deprecated, now we should use RendererV2 (see line below). See the commit.-
10/03/2017:
RendererV2 was renamed to Renderer2. See the breaking changes.RendererV2 has no more listenGlobal function for global events (document, body, window). It only has a listen function which achieves both functionalities.For reference, I'm copy & pasting the source code of the DOM Renderer implementation since it may change (yes, it's angular!).
listen(target: 'window'|'document'|'body'|any, event: string, callback: (event: any) => boolean):
() => void {
if (typeof target === 'string') {
return void>this.eventManager.addGlobalEventListener(
target, event, decoratePreventDefault(callback));
}
return void>this.eventManager.addEventListener(
target, event, decoratePreventDefault(callback)) as() => void;
}
As you can see, now it verifies if we're passing a string (document, body or window), in which case it will use an internal
addGlobalEventListener function. In any other case, when we pass an element (nativeElement) it will use a simple addEventListenerTo remove the listener it's the same as it was with
Renderer in angular 2.x. listen returns a function, then call that function.Example
// Add listeners
let global = this.renderer.listen('document', 'click', (evt) => {
console.log('Clicking the document', evt);
})
let simple = this.renderer.listen(this.myButton.nativeElement, 'click', (evt) => {
console.log('Clicking the button', evt);
});
// Remove listeners
global();
simple();
plnkr with Angular 4.0.0-rc.1 using RendererV2
plnkr with Angular 4.0.0-rc.3 using Renderer2
Context
Stack Overflow Q#35080387, score: 293
Revisions (0)
No revisions yet.