• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Using DOM Event Listeners In Aurelia

Aurelia 1, Aurelia 1 Tutorials · February 11, 2016

When it comes to using a plain old event listener in your Aurelia applications, if you are not aware of how classes work and how things get transpiled, then you will most likely run into some issues working with events and scope.

First you might try something like the following:

export MyClass {
    attached() {
        document.addEventListener('click', this.handleBodyClick);
    }

    detached() {
        document.removeEventListener('click', this.handleBodyClick);
    }

    handleBodyClick(e) {
        console.log(e.target);
    }
}

On the surface everything looks fine, it should work right? Sorry, but this will not work. Many first timers implementing event listeners into their apps will run into this, heck I even ran into it once as well.

The scope of the callback function in this instance due to how event listeners work will not be the current class. So you will lose reference to the current class scope, the value of this becomes that of the outer function that created it or something like that.

The right away to attach event listeners in Aurelia:

export MyClass {
    constructor() {
        this.handleBodyClick = e => {
            console.log(e.target);
        };
    }

    attached() {
        document.addEventListener('click', this.handleBodyClick);
    }

    detached() {
        document.removeEventListener('click', this.handleBodyClick);
    }   
}

Worth pointing out here is that you should always attach your events in the Aurelia attached lifecycle method and detach them in the detached lifecycle method.

While the thought of creating a function in your constructor might make some cringe, due to the way event listeners work as per the spec, there is really no other choice.

You might be able to use bind on your addEventListener like this this.handleBodyClick.bind(this) but bind can introduce issues into your app and arrow functions are arguably the way to go.

Dwayne

Leave a Reply Cancel reply

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
cnlevy
cnlevy
7 years ago

what issues are introduced by bind ? Also, the bind notation would keep code cleaner, as the callback function could be declared statically in the class, and not created dynamically inside the constructor

0
bigopon
bigopon
6 years ago

Creating new function in attached requires you to keep a reference to it to remove listener in detached, I think that’s the problem.

But i don’t know how to create handler statically without binding.

0
Daniel Jenikovský
Daniel Jenikovský
6 years ago

What about using ‘() => {}’ (lambda) syntax? I’m not sure about ECMA script but in typescript works really well and persists scope – it doesn’t compile to .bind, it creates a local copy of this as _this and uses that.

example:

attached() {
window.addEventListener(“load”, e => this.eventHandler(e));
}

0
Greg Gum
Greg Gum
4 years ago

Awesome work Dwayne, keep up the good work!

0

Primary Sidebar

Popular

  • How To Get The Hash of A File In Node.js
  • Handling Errors with the Fetch API
  • Testing Event Listeners In Jest (Without Using A Library)
  • Thoughts on the Flipper Zero
  • Waiting for an Element to Exist With JavaScript

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz