0

I want to create a Mapbox IControl object, which zooms the map in when a button in the control is clicked.

This is my custom IControl class:

class customControl {
  _map;
  _container;
  _myButton;

  constructor() {
    this._myButton = document.createElement('button');
    this._myButton.className = 'mapboxgl-ctrl-zoom-in';
    this._myButton.type = 'button';
    this._myButton.title = 'Test';
    this._myButton.onclick = this._myAction;

    this._container = document.createElement('div');
    this._container.className = 'mapboxgl-ctrl-group mapboxgl-ctrl';
    this._container.appendChild(this._myButton);
  }

  onAdd(map) {
    this._map = map;
    return this._container;
  }

  onRemove() {
    this._container.parentNode.removeChild(this._container);
    this._map = undefined;
  }

  _myAction() {
    const map = this._map;
    console.log(this._map);
    map.zoomIn();
  }
}

I add this control to my map using the following code:

let myControl = new customControl();
map.addControl(myControl, 'bottom-left');

When the button is clicked, I however get an Cannot read properties of undefined (reading 'zoomIn') error message, since this._map is obviously undefined. When I remove the const map = this._map; line from the _myAction() function, the zoom in works as expected, but the global map object is used.

Why is this._map undefined in _myAction()? Is there a way to make _myAction() aware of the "scope" the button is clicked, so I can access properties of my custom IControl when clicked?

derhansen
  • 5,585
  • 1
  • 19
  • 29

1 Answers1

1

I encountered something similar.

I think you are suffering from an 'unbound this' reference... see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#binding_this_with_instance_and_static_methods

So you should be able to fix it by changing the line in your constructor to either of the following: this._myButton.onclick = this._myAction.bind(this);

OR

this._myButton.onclick = () => this._myAction();

Personally I find the second syntax easier to read.

marracuene
  • 142
  • 11