3

I'm a new leaflet learner with React typescript. Want to create a custom button on the map. On clicking the button a popup will appear. I saw many example but they are all based on older version and I also tried to create my own but no luck. The documentation also not providing much help. Even a functional custom control component is also very effective for my app. Any help on this will be much appreciated. Here is my code,

Custom button

import React, { Component } from "react";
import { useMap } from "react-leaflet";
import L, { LeafletMouseEvent, Map } from "leaflet";

class Description extends React.Component<{props: any}> {
  createButtonControl() {
    const MapHelp = L.Control.extend({
      onAdd: (map : Map) => {
        const helpDiv = L.DomUtil.create("button", ""); //how to pass here the button name and
        //other property ?
        
        //a bit clueless how to add a click event listener to this button and then
        // open a popup div on the map

      }
     
    });
    return new MapHelp({ position: "bottomright" });
  }

  componentDidMount() {
    const { map } = this.props as any;
    const control = this.createButtonControl();
    control.addTo(map);
  }

  render() {
    return null;
  }
}

function withMap(Component : any) {
  return function WrappedComponent(props : any) {
    const map = useMap();
    return <Component {...props} map={map} />;
  };
}

export default withMap(Description);

The way I want to call it

<MapContainer
        center={defaultPosition}
        zoom={6}
        zoomControl={false}
        >
             <Description />
            

             <TileLayer
                attribution="Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL."
                url="https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png"
            />
            <ZoomControl position={'topright'}/>
        </MapContainer>

1 Answer 1

4

You're close. Sticking with the class component, you just need to continue creating your buttons instance. You can use a prop on Description to determine what your button will say and do:

      <Description
        title={"My Button Title"}
        markerPosition={[20.27, -157]}
        description="This is a custom description!"
      />

In your decsription's createButtonControl, you're almost there. You just need to fill it out a bit:

createButtonControl() {
    const MapHelp = L.Control.extend({
      onAdd: (map) => {
        const helpDiv = L.DomUtil.create("button", "");
        this.helpDiv = helpDiv;
        // set the inner content from the props
        helpDiv.innerHTML = this.props.title;

        // add the event listener that will create a marker on the map
        helpDiv.addEventListener("click", () => {
          console.log(map.getCenter());
          const marker = L.marker()
            .setLatLng(this.props.markerPosition)
            .bindPopup(this.props.description)
            .addTo(map);

          marker.openPopup();
        });
 
        // return the button div
        return helpDiv;
      }
    });
    return new MapHelp({ position: "bottomright" });
  }

Working codesandbox

There's a million ways to vary this, but hopefully that will get you going.

3
  • Definitely it helps me get going.Thank you very very much. Leaflet is such a beautiful library but sad it doesn't have good documentation but the supporting community rocks !!! thanks much !!!
    – sandy
    Commented Jul 17, 2021 at 5:46
  • Just a question, instead of a marker and popup on button click, if I want to create a description div that contains some helping notes with some icons about the map, it is still possible... right? In that case can I use a material UI dialog box or I've to use a leaflet tooltip/popup and place my custom component (dialog box) on that ? I noticed the popup has a size limitation so is there any other option to lay a div on top of the map ?
    – sandy
    Commented Jul 17, 2021 at 5:52
  • and secondly, you said many other variation possible. Could you please provide another example to do it. Specially with hooks. Even another variation with class based approach is alos great. I'm learning leaflet so it would be really helpful.
    – sandy
    Commented Jul 17, 2021 at 5:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.