0

In plain JavaScript, consider the following: You want to have an object that has its own rendering method, and inside the rendering is a button that is to call another of the object’s functions.

As a basic example:

class Person () {
    //...

    incrementAge() { this.age++ }

    render() {
        return "<button onClick='this.incrementAge()'>Age += 1</button>"
    }
}

Now, as you probably realize, this button will fail because this refers to the click event now, and not the object itself.

Question

What’s the solution to making this button call the object’s function?

Sebastian Simon
  • 14,320
  • 6
  • 42
  • 61
Alec
  • 1,539
  • 4
  • 15
  • 37
  • 1
    `this` will refer to the button, not the click event. Inline event handlers like `onclick` are [not recommended](https://stackoverflow.com/q/11737873/4642212). They are an [obsolete, hard-to-maintain and unintuitive](https://stackoverflow.com/a/43459991/4642212) way of registering events. Always [use `addEventListener`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Inline_event_handlers_—_dont_use_these) instead. – Sebastian Simon Jan 18 '21 at 14:37
  • Try using [event delegation](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) instead — it’s more maintainable, and applies to dynamically added (e.g. “rendered”) elements. E.g., use an [event argument](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback)’s [`target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target). See [the tag info](https://stackoverflow.com/tags/event-delegation/info) and [What is DOM Event delegation?](https://stackoverflow.com/q/1687296/4642212). – Sebastian Simon Jan 18 '21 at 14:38
  • @charlietfl - It is explicitly vanilla. If it were React, I would have returned an HTML object without the quotes :) – Alec Jan 18 '21 at 14:40
  • @SebastianSimon - Thanks for the link! I will read up on it and try to avoid the onClick methodology. – Alec Jan 18 '21 at 14:40

1 Answers1

1

It's actually a bad practice to type javascript code in a string. You won't get code completion or error checking in your IDE.

Perhaps it's better to just return an actual HTML component? That will give you error handling AND you can add listeners to the button without using querySelector to find your own element.

If you use the ()=> notation in the render method, this will keep referring to the Person class, so you can still say this.age++.

class Person {
    constructor(){
        this.age = 10
    }
    
    incrementAge() { 
       this.age++ 
    }
    
    render() {
       const btn = document.createElement("button")
       btn.innerText = "Age += 1"
       btn.addEventListener("click", () => this.incrementAge())
       return btn
     }
}

// usage
let p = new Person()
let element = p.render()
document.getElementById("app").appendChild(element)

Codepen sketch : https://codepen.io/eerk/pen/VwKgXLO

Kokodoko
  • 19,176
  • 21
  • 88
  • 153