3

Imagine having a class that generates content on the page. Part of the content should have event listener attached in html such as onclick=function().

How can I make sure to call the function from within the class that constructed the html?

class Container {
  constructor(hook) {
    this.hook = "#" + hook;
    this.addDiv = this.addDiv.bind(this);
    this.fireMe = this.fireMe.bind(this);
    this.init = this.init.bind(this);
    this.init();
  }
  addDiv() {
    const div = `<div onclick="fireMe()">FIRE ME</div>`;
    document.querySelector(this.hook).innerHTML = div;
  }
  fireMe() {
    console.log("hello!");
  }
  init() {
    this.addDiv();
  }
}

let div = new Container("app");

now getting error that fireMe is undefined (which is right because it is not available in global scope).

I know I can add event listener by rendering the div first and than adding the event listener, but is there a way of adding event listener from within <div> tag to actually reach Container.fireMe() method?

Dom
  • 645
  • 6
  • 17
  • 2
    Events inline in the `DOM` look for the function to be declared in the *global scope*. Use an event listener instead. Also, I'd suggest creating the `
    ` as an *element* instead of using an HTML string and `innerHTML`.
    – Tyler Roper Jan 30 '19 at 14:56
  • Thank you, I thought that would be the case – Dom Jan 30 '19 at 15:00

3 Answers3

3

You have to create the element -> something like this

class Container {
  constructor (hook) {
    this.hook = '#' + hook;
    this.addDiv = this.addDiv.bind(this);
    this.fireMe = this.fireMe.bind(this);
    this.init = this.init.bind(this);
    this.init();
  }

  addDiv () {
    const div = document.createElement('div');
    div.textContent = 'FIRE ME';
    div.addEventListener('click', this.fireMe );
    document.querySelector(this.hook).innerHTML = div;
  }

  fireMe () {
    console.log('hello!');
  }

  init () {
    this.addDiv();
  }
}

const div = new Container('app');
d-h-e
  • 2,478
  • 1
  • 10
  • 18
2

Never use inline event handlers as there are many reasons to avoid this 20+ year old technique that just will not die.

Instead, use modern, standards-based code with .addEventListener(). If you do this along with making the new HTML using the DOM API, you'll be able to more easily accomplish your goal:

addDiv() {
  const div = document.createElement("div");
  div.textConent = "FIRE ME";
  div.addEventListener("click", this.fireMe);
  document.querySelector(this.hook).innerHTML = div;
}
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

You should create elements use document.createElement() rather than using string

class Container {
  constructor(hook) {
    this.hook = "#" + hook;
    this.addDiv = this.addDiv.bind(this);
    this.fireMe = this.fireMe.bind(this);
    this.init = this.init.bind(this);
    this.init();
  }
  addDiv(){
    const div = document.createElement('div');
    div.innerHTML = "Fire Me";
    div.addEventListener("click",this.fireMe);
    document.querySelector(this.hook).appendChild(div);
  }
  fireMe() {
    console.log("hello!");
  }
  init() {
    this.addDiv();
  }
}
let div = new Container("app");
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • `document.querySelector(this.hook).appendChild(div);` will add the node to the element, where the OP is replacing the current node with a new one. – Scott Marcus Jan 30 '19 at 15:08