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 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.
I aso find this extremely confusing. as @EricMartinez points out Renderer2 listen() returns the function to remove the listener:
If i´m adding a listener
I´d expect my function to execute what i intended, not the total opposite which is remove the listener.
In the given scenario, It´d actually make to more sense to name it like:
There must be a good reason for this but in my opinion it´s very misleading and not intuitive.
Here's my workaround:
I created a library with Angular 6. I added a common component
commonlib-header
which is used like this in an external application.Note the
serviceReference
which is the class (injected in the componentconstructor(public serviceReference: MyService)
that uses thecommonlib-header
) that holds thestringFunctionName
method:The library component is programmed like this. The dynamic event is added in the
onClick(fn: any)
method:The reusable
header.component.html
:Renderer has been deprecated in Angular 4.0.0-rc.1, read the update below
The angular2 way is to use
listen
orlistenGlobal
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
)You can use
listenGlobal
that will give you access todocument
,body
, etc.Note that since beta.2 both
listen
andlistenGlobal
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
orlistenGlobal
to a variable that will hold the function returned, and then we execute it.Here's a plnkr with an example working. The example contains the usage of
listen
andlistenGlobal
.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(see line below). See the commit.RendererV2
10/03/2017:
RendererV2
was renamed toRenderer2
. See the breaking changes.RendererV2
has no morelistenGlobal
function for global events (document, body, window). It only has alisten
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!).
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 simpleaddEventListener
To 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
plnkr with Angular 4.0.0-rc.1 using RendererV2
plnkr with Angular 4.0.0-rc.3 using Renderer2