Search code examples
angulartypescriptleafletngx-leaflet

ngx-leaflet: How to add a custom control?


I have tried for a while now to implement this leaflet tutorial using the ngx-leaflet.

There is absolutely no clear documentation on how to implement a custom control or legend while following along with the tutorial.

var info = L.control();

info.onAdd = function (map) {
    this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
    this.update();
    return this._div;
};

// method that we will use to update the control based on feature properties passed
info.update = function (props) {
    this._div.innerHTML = '<h4>US Population Density</h4>' +  (props ?
        '<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>'
        : 'Hover over a state');
};

info.addTo(map);

enter image description here

Same goes for creating a legend.

Can any point me in the right direction to try and get this implemented in Angular 7 with ngx-leaflet lib?

import { control, featureGroup, geoJson, icon, latLng, LatLngExpression, Map, Marker, marker, popup, tileLayer } from 'leaflet';

  onMapReady(map: Map) {
    this.map = map;

    // create info control
    let info = control(
      {
        onAdd: map => {

        }
      }
    )
    info.addTo(map);

I get that you need to do something like this, but I don't want to add a circle or shape, but the custom control in the screenshot above as well as a legend.


Solution

  • The only thing you need to do to make this example work is to listen to onMapReady event & place all the code of the tutorial inside there. Map reference is what you want and it comes as an argument to this function.

    Specifically:

    <div
      style="height: 100vh"
      leaflet
      [leafletOptions]="options"
      (leafletMapReady)="onMapReady($event)"
    ></div>
    

    ts:

    onMapReady(map) {
     // place all the tutorial code inside here
     ...
    
    // control that shows state info on hover
    let info = L.control();
    
    // here you want the reference to be info, therefore this = info
    // so do not use es6 to access the the class instance
    info.onAdd = function (map) {
      this._div = L.DomUtil.create('div', 'info');
      this.update();
      return this._div;
    };
    
    // also here you want the reference to be info, therefore this = info
    // so do not use es6 to access the class instance
    info.update = function (props) {
      this._div.innerHTML = '<h4>US Population Density</h4>' + (props ?
        '<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>'
        : 'Hover over a state');
    };
    
    info.addTo(map);
    ...
    const legend = L.control({ position: 'bottomright' });
    
    legend.onAdd = map => {
    
      let div = L.DomUtil.create('div', 'info legend'),
        grades = [0, 10, 20, 50, 100, 200, 500, 1000],
        labels = [],
        from, to;
    
      for (var i = 0; i < grades.length; i++) {
        from = grades[i];
        to = grades[i + 1];
    
        labels.push(
          '<i style="background:' + getColor(from + 1) + '"></i> ' +
          from + (to ? '&ndash;' + to : '+'));
      }
    
      div.innerHTML = labels.join('<br>');
      return div;
    };
    
    legend.addTo(map);
    }
    

    Check the demo for the full example in Angular 7 using ngx-leaflet