0

How to bind a class method in to click-event?

In this sample, the context is button. I've also tried the arrow-notation, without any success.

"use strict";
class Foo {
    constructor() {
        $('html').prepend('<button id="btn">Click me!</button>');
        $('#btn').bind('click', this.clickEvents);
    }

    clickEvents(e) {
      //Have to use as a function, otherwise unbind won't work
        e.stopPropagation();
        // How to point to sayBoo-function?
        debugger;
        this.sayBoo(); //Points to <button id="btn"...
    }
  
    doUnBindings(){
      $('#btn').unbind('click', this.clickEvents);
    }

    sayBoo() {
        alert('boo');
    }
}

const f = new Foo(); // eslint-disable-line no-unused-vars, prefer-const
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.33.1/es6-shim.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Yours H

Heikki Mustonen
  • 301
  • 3
  • 15

2 Answers2

2

In your constructor you need to bind clickEvents to this

$('#btn').bind('click', this.clickEvents.bind(this));

And since it looks like you want to remove your even listener later on you should actually store a reference to that bound function because that's what you'll need to use in your doUnBindings method.

So ultimately you probably want something that looks like this

"use strict";
class Foo {
    constructor() {
        $('html').prepend('<button id="btn">Click me!</button>');
        this.boundClickEvents = this.clickEvents.bind(this);
        $('#btn').bind('click', this.boundClickEvents);
    }

    clickEvents(e) {
      //Have to use as a function, otherwise unbind won't work
        e.stopPropagation();
        // How to point to sayBoo-function?
        debugger;
        this.sayBoo(); //Points to <button id="btn"...
    }

    doUnBindings(){
      $('#btn').unbind('click', this.boundClickEvents);
    }

    sayBoo() {
        alert('boo');
    }
}
Jonathan
  • 1,241
  • 9
  • 16
  • This works great. I was hoping that ES6 would bring less hacky solutions for the common patterns. – Heikki Mustonen Aug 26 '15 at 16:12
  • I wouldn't call function binding hacky, but if you're looking for a more idiomatic way of doing things you might want to try combining Bergi's solution with this one by calling this.clickEvents inside the arrow function. I wouldn't actually recommend that though since it would be relying on an arrow function for nothing more than what bind already does. And it would require you to forward the event arguments. – Jonathan Aug 26 '15 at 16:46
2

You can easily use the arrow notation here, just create the instance-specific method in the constructor:

class Foo {
    constructor() {
        this.clickEvents = (e) => {
            e.stopPropagation();
            this.sayBoo();
        };
    }
    doBindings() {
        $('#btn').bind('click', this.clickEvents);
    }
    doUnbindings(){
        $('#btn').unbind('click', this.clickEvents);
    }
    sayBoo() { … }
}

Alternatively you can use bind as fleshed out by @Jonathan, or any of the standard approaches.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375