How can I trigger a customEvent in JavaScript?

42 views Asked by At

I am trying to implement a simple game in JavaScript where the game itself is one class and the info about the game is the other. The info must be updated after each time the user clicks the mouse. I have two classes. The Grid class is the game itself. This is simplification:

class Grid {
  constructor(container) {
    this.container = container;
    this.myEvent = new Event("myCustomEvent")
    this.container.addEventListener('click', () => {
      this.container.addEventListener("myCustomEvent", e => {
        console.log(e)
      })
    })
  }

And this is the Info class.

class Info {
  constructor(grid, container) {
    this.container = container;
    this.grid = grid;
    this.container.dispatchEvent(this.myEvent)
  }

I then create the instances of the two classes:

const grid = new Grid(document.querySelector(".container"));
const info = new Info(grid, document.querySelector(".container"));

However this does nothing. Is there a way to dynamically update and display the information that exists in one class but must be passed to another? I don't want to mix these two classes into one.

I can see that this works. It logs out the event:

class Grid {
  constructor(container) {
    this.container = container;
    this.myEvent = new Event("myCustomEvent")
    this.container.addEventListener("myCustomEvent", e => {
      console.log(e)
    })
    this.container.dispatchEvent(this.myEvent)
  }
const grid = new Grid(document.querySelector(".container"));

However not when I dispatch the event in a different class.

1

There are 1 answers

1
Alexander Nenashev On

You get your code wrong:

class Info {
  constructor(grid, container) {
    this.container = container;
    this.grid = grid;
    this.container.dispatchEvent(this.myEvent) // here it should be grid.myEvent
  }

Note that if you create the Info's instance before the clicking on the grid container, you will dispatch the event into nowhere, nothing will happen:

const grid = new Grid(document.querySelector(".container"));
// you need to click the grid container first...
const info = new Info(grid, document.querySelector(".container"));

That was about your first snippet of Grid. The second one would work. Please prepare a working code snippet next time... You've managed to spoil us with 2 different version of your Grid.

But I think your code isn't perfect. Your goal is decoupling but your Info class has Grid as a dependency. You try to communicate with events and that's a good architecture. For some reason you try DRY too hard and manage to define your custom event in one place. Not a good way to go, just remove the Grid dependency and emit the event in Info agnostically to any Grid class:

class Grid {
  constructor(container) {
    this.container = container;
    this.container.addEventListener('click', () => {
      this.container.addEventListener("myCustomEvent", e => {
        console.log(e)
      })
    })
  }

class Info {
  constructor(container) {
    this.container = container;
    this.container.dispatchEvent(new Event('myCustomEvent'))
  }