Your best bet would be not to use markup, since the function you call from an onxyz
-attribute-style event handler has to be a global.
Instead, create the element and then assign the function to it:
class MyClass {
constructor() {
}
handleClick(e) {
alert('clicked');
}
render() {
var input = document.createElement("input");
input.type = "radio";
input.addEventListener("click", e => this.handleClick(e));
return input;
}
}
window.addEventListener('load', init);
function init() {
const myClassInstance = new MyClass();
const el = document.getElementsByClassName('myelement')[0];
el.appendChild(myClassInstance.render());
}
<div class="myelement"></div>
Note the use of an arrow function so that this
is correct when we call this.handleClick
. Obviously, you don't need it for just an alert
, but I assume you'll want to use properties of the instance of MyClass
. (To access the element on which the click occurred, use e.currentTarget
since it won't be this
.)
If you have a strong preference to do this with markup, an option would be:
- Have an
initEvents
method or similar that consumers of the class are supposed to call (like they're supposed to call render
)
- Use a unique ID in the markup
- Use that ID to find the element and hook up events
Or better yet: Have render
accept the element to add to, and do the event hookup after adding it.
But working with your existing render
approach:
const MyClass = (() => {
let nextId = 1;
class MyClass {
constructor() {
this.id = `__MyClass__${nextId++}`;
}
handleClick(e) {
alert('clicked');
}
render() {
return `<input type="radio" id="${this.id}" />`;
}
initEvents() {
const e = document.getElementById(this.id);
if (!e) {
throw new Error("initEvents must be called after appending the markup from render to the DOM");
}
e.addEventListener("click", e => this.handleClick(e));
}
}
return MyClass;
})();
window.addEventListener('load', init);
function init() {
const myClassInstance = new MyClass();
const el = document.getElementsByClassName('myelement')[0];
el.insertAdjacentHTML('beforeend', myClassInstance.render());
myClassInstance.initEvents();
}
<div class="myelement"></div>