15

I've added custom buttons to my MapBox map and they shop up correctly. However when I add a click listener it does not work. I see no error in my console.

The code looks like this:

const currentLocationControl = new CustomControl('current-location-control', 'GPS');

this.map.addControl(currentLocationControl, 'top-left');

document.getElementById('test').addEventListener('click', function (e) {
    alert('test');
});

I execute this code in the mounted method from vue.js.

The CustomControl:

export default class CustomControl {

    constructor(className, text) {
        this.className = className;
        this.text = text;
    }

    onAdd(map){
        this.map = map;
        this.container = document.createElement('div');
        this.container.id = 'test';
        this.container.className = this.className;
        this.container.textContent = this.text;
        return this.container;
    }
    onRemove(){
        this.container.parentNode.removeChild(this.container);
        this.map = undefined;
    }
}

When I console.log(document.getElementById('test')); I see the expected result in my console (the test div).

enter image description here

So what could be going on here?

Jenssen
  • 1,801
  • 4
  • 38
  • 72
  • 1
    It's most likely due to the fact that you're building this in javascript so it's not available in the DOM when you're attempting to bind to use. use event delegation off of the closest static parent element instead – Ohgodwhy Apr 07 '18 at 17:51
  • Anyone????!?!?! – Jenssen Apr 08 '18 at 14:06
  • 1
    Did you attempt what I told you? – Ohgodwhy Apr 08 '18 at 14:48
  • @ohgodwhy it's within a vue.js component so there is no static parent right? Thanks for helping. – Jenssen Apr 08 '18 at 15:32
  • Just put a breakpoint at that speciffic line and check if the element is trully there. Also, the event can be bound but the button may appear under the map, so you actually click on themap not the button. Do you have correct z-indexes? – knaos Apr 17 '18 at 08:21
  • It would be best if you provide a working Plunker example – knaos Apr 17 '18 at 08:21

2 Answers2

2

To make sure that the click event is bind to the correct element, you can bind the event in the Class declaration instead.

Pass a callback for click event to the CustomControl

const clickCallback = function(e) {
  alert(test);
};

const currentLocationControl = new CustomControl(
  "current-location-control",
  "GPS",
  clickCallback
);

Class declaration:

// add clickCallback to constructor
export default class CustomControl {
  constructor(className, text, clickCallback) {
    //...
  }

  onAdd(map) {
    //...
    this.container.onclick = clickCallback;
    //...
  }
}
Jacob Goh
  • 19,800
  • 5
  • 53
  • 73
1

It might very well be the element does not yet exist, depending on how map.addControl works.

Perhaps if you created a method in your CustomControl to return the container, and instead of using document.getElementById you'd use something like currentLocationControl.getContainer()?

Alternatively a setAction in your CustomControl like

setAction(action) {
    this.container.addEventListener('click', action);
}
Erik Lumme
  • 5,202
  • 13
  • 27