Leaflet – How to Add Popup on Layer Click Using Vue3

leafletvue.js

I am building a web app using Vue 3 and Leaflet. I use the vue-leaflet plugin.

I have a background map and overlay layers, namely WMS tile layers served by Geoserver.

Now I want a popup to open at the location(lat, long) where I click on the layer. For the vue-leaflet plugin I could only find examples for adding a popup to markers, circles or geometries but no example for popups on layers.

To start off, I tried defining a leaflet function that adds a popup to the map when a click event is executed. but that throws me an error. The relevant code snippet and error log attached.

How can I approach this using either the vue-leaflet plugin or a pure leaflet script?

// HTML

<div id="bg-map">
    <l-map
      ref="map"
      v-model="zoom"
      v-model:zoom="zoom"
      :center="center"
      :options="{zoomControl:false, attributionControl:false}"
      :minZoom="minzoom"
      @click="addPopUp"
    >

    <!-- Layers from Geoserver as cached tile layers: -->
    <l-wms-tile-layer
      v-for="wmsLayer in getCheckedLayers"
      :key="wmsLayer.path"
      :layers="wmsLayer.path"
      :format="format_tile"
      :transparent="true"
      :tiled="true"
      :zIndex="wmsLayer.zindex"
      :base-url="wmsurl"
      :visible="true"
      :opacity="wmsLayer.opacity"
    >
    </l-wms-tile-layer> 

// JS

methods: {

    addPopUp(e) {
      const map = this.$refs.map.leafletObject;
      var popLocation = e.latlng;
      var popup = new L.popup()
      .setLatLng(popLocation)
      .setContent('<p> Hello popup </p>')
      .openOn(map)
    },

// error log

Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at NewClass._updateContent (leaflet-src.esm.js?6bb3:9617:1)
    at NewClass.update (leaflet-src.esm.js?6bb3:9528:1)
    at NewClass.onAdd (leaflet-src.esm.js?6bb3:9465:1)
    at NewClass.onAdd (leaflet-src.esm.js?6bb3:9751:1)
    at NewClass._layerAdd (leaflet-src.esm.js?6bb3:6561:1)
    at Proxy.whenReady (leaflet-src.esm.js?6bb3:4422:1)
    at Proxy.addLayer (leaflet-src.esm.js?6bb3:6623:1)
    at Proxy.openPopup (leaflet-src.esm.js?6bb3:9975:1)
    at NewClass.openOn (leaflet-src.js?e11e:9752:1)
    at Proxy.addPopUp (BGMap.vue?112f:315:1)

Best Answer

I ended up with a workaround solution: By setting an invisible marker when clicking at any point of the map. The marker has an open popup by default. In the end it looks like a popup opens when clicking the map.

// HTML Call the addMarker method when clicking on the map. Marker component with popup

<div id="bg-map">
    <l-map
      ref="map"
      v-model="zoom"
      v-model:zoom="zoom"
      :center="center"
      :options="{zoomControl:false, attributionControl:false}"
      :minZoom="minzoom"
      @click="addMarker"
    >

    <l-marker ref="marker" :lat-lng="marker" :options="markerOptions"> 
      <l-icon :icon-size= [1,1] icon-url="icon.png"> </l-icon>
      <l-popup ref="popup">
       Popup content
      </l-popup>
    </l-marker>

</div>

// JS

export default {
   data(){
      return {
         marker: [0,0], # default lat-lng for marker
         markerOptions: {opacity: 0, width:"1px", height:"1px"}, #marker icon is small and invisible
      }
   },
   methods: {
      addMarker(e) {

      // set marker at latlng position
      this.marker = e.latlng;

      // open popup on marker with a delay of 100 ms
      setTimeout(() => 
        this.$refs.marker.leafletObject.openPopup(), 100);
      }
   }
} 
 
Related Question