jperelli / vue2-leaflet-markercluster

markercluster plugin extension for vue2-leaflet package
MIT License
132 stars 55 forks source link

Error in mounted hook: "TypeError: this._featureGroup.addEventParent is not a function" #44

Open EarthmanWeb opened 4 years ago

EarthmanWeb commented 4 years ago

Hi, I've installed this in a Webpack project using Vue CLI 4 When I don't use the v-marker-cluster component, all works fine

Modules/versions in question:

{
    "leaflet": "^1.3.4",
    "leaflet-css": "^0.1.0",
    "leaflet-fullscreen": "^1.0.2",
    "leaflet.markercluster": "^1.4.1",
    "vue2-leaflet": "^2.0.0",
    "vue2-leaflet-markercluster": "^3.1.0"
}

When I try to use, with the syntax provided, I get an error:

[Vue warn]: Error in mounted hook: "TypeError: this._featureGroup.addEventParent is not a function"

found in

---> <VMarkerCluster>
       <LMap>
         <HostMap> at src/views/HostMap.vue
           <VNavigationDrawer>
             <VApp>
               <App> at src/App.vue
                 <Root>

Here is the contents of my package.json:

{
  "name": "cwp_map_2-2",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@mdi/font": "^3.6.95",
    "@riophae/vue-treeselect": "^0.4.0",
    "@types/leaflet": "^1.5.12",
    "babel-loader": "^8.1.0",
    "core-js": "^3.6.4",
    "esri-leaflet": "^2.4.1",
    "fuse.js": "^5.1.0",
    "leaflet": "^1.3.4",
    "leaflet-css": "^0.1.0",
    "leaflet-fullscreen": "^1.0.2",
    "leaflet.markercluster": "^1.4.1",
    "lodash": "^4.17.15",
    "moment": "^2.24.0",
    "register-service-worker": "^1.6.2",
    "roboto-fontface": "*",
    "save": "^2.4.0",
    "vue": "^2.5.17",
    "vue-image-lightbox": "^7.0.0",
    "vue-lazyload": "^1.3.3",
    "vue-masonry": "^0.11.8",
    "vue-resize-text": "^0.1.1",
    "vue-router": "^3.1.5",
    "vue-scrollto": "^2.18.1",
    "vue-touch-events": "^1.0.3",
    "vue2-leaflet": "^2.0.0",
    "vue2-leaflet-markercluster": "^3.1.0",
    "vuetify": "^2.2.11",
    "vuex": "^3.1.2"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.2.0",
    "@vue/cli-plugin-eslint": "~4.2.0",
    "@vue/cli-plugin-pwa": "~4.2.0",
    "@vue/cli-plugin-router": "~4.2.0",
    "@vue/cli-plugin-vuex": "~4.2.0",
    "@vue/cli-service": "~4.2.0",
    "@vue/eslint-config-standard": "^5.1.0",
    "axios": "^0.18.0",
    "babel-eslint": "^10.0.3",
    "chrome-launcher": "^0.13.3",
    "css-loader": "^3.6.0",
    "eslint": "^6.7.2",
    "eslint-plugin-import": "^2.20.1",
    "eslint-plugin-node": "^11.0.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.0",
    "eslint-plugin-vue": "^6.1.2",
    "less": "^3.0.4",
    "less-loader": "^5.0.0",
    "sass": "^1.19.0",
    "sass-loader": "^8.0.0",
    "vue-cli-plugin-axios": "0.0.4",
    "vue-cli-plugin-vuetify": "~2.0.5",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.3.0"
  }
}

Here is my component code:

<style lang="scss">
  @import '../../node_modules/leaflet.markercluster/dist/MarkerCluster.css';
  @import '../../node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css';
</style>
<template>
  <div :style="mapStyle">
    <v-map ref="mymap" :style="mapStyle" :zoom="zoom" :center="center">
      <v-icondefault :image-path="'/statics/leafletImages/'"></v-icondefault>
      <v-tilelayer :url="url"></v-tilelayer>
      <v-marker-cluster>
        <v-marker :lat-lng="marker">
          <v-popup content="test content"></v-popup>
        </v-marker>
      </v-marker-cluster>
    </v-map>
  </div>
</template>
<script>
import Vue from 'vue'
import { mapState, mapGetters } from 'vuex'
import store from '@/store/'
import L from 'leaflet'
import leafletCss from 'leaflet-css'
import { LMap, LTileLayer, LMarker, LLayerGroup, LFeatureGroup, LIconDefault, LPopup } from 'vue2-leaflet'
import Vue2LeafletMarkerCluster from 'vue2-leaflet-markercluster'

export default {
  components: {
    'v-map': LMap,
    'v-icondefault': LIconDefault,
    'v-tilelayer': LTileLayer,
    'v-marker': LMarker,
    'v-popup': LPopup,
    'v-marker-cluster': Vue2LeafletMarkerCluster
  },
  data () {
    return {
      windowHeight: '0',
      windowWidth: '0',
      zoom: store.state.mapStartZoom,
      center: L.latLng(store.state.mapStartLat, store.state.mapStartLng),
      url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      marker: L.latLng(store.state.mapStartLat, store.state.mapStartLng)
    }
  },
  computed: {
    ...mapGetters([
      'getIsMobile',
      'getHostsFiltered',
      'getHosts'
    ]),
    mapStyle () {
      var multiplier = 1
      if (!this.getIsMobile) {
        multiplier = 0.4
      }
      // size to the right height and width on load
      return 'height:' + this.windowHeight + 'px;width:' + (this.windowWidth * multiplier) + 'px; margin:0px; padding: 0px;'
    }
  },
  created () {
    this.$nextTick(() => {
      const map = this.$refs.mymap.mapObject
      const esri = require('esri-leaflet')
      esri.basemapLayer('Topographic').addTo(map)
      window.addEventListener('resize', this.onResize, false) // resize the map on load
      this.windowHeight = window.innerHeight - 105
      this.windowWidth = window.innerWidth
      this.renderComponent = true
      map._onResize() // refresh the changes
    }, (this))
  },
  destroyed () {
    window.removeEventListener('resize', this.onResize)
  },
  methods: {
    onResize () {
      // resize the map when the window is resized
      this.windowHeight = window.innerHeight - 105
      this.windowWidth = window.innerWidth
    },
    getMarkerLatLng (host) {
      // console.log('host', host)
      if (host.lat && host.lon) {
        return L.latLng(host.lat, host.lon)
      }
    },
    getHostsMap () {
      if (store.state.mapShowAllHosts) {
        return this.getHosts
      } else {
        return this.getHostsFiltered
      }
    }
  }
}
</script>

As far as I can tell by the documentation, there should not be a problem.

Can you please offer me any ideas why I may be getting this error?

EarthmanWeb commented 4 years ago

FYI - I downgraded the versions, trying to find compatible ones, but so far no luck.

I started with the default versions installed with each module

EarthmanWeb commented 4 years ago

When I bypass this module, all is working as expected:

<style lang="scss">
  @import '../../node_modules/leaflet.markercluster/dist/MarkerCluster.css';
  @import '../../node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css';
</style>
<template>
  <div :style="mapStyle">
    <v-map ref="mymap" :style="mapStyle" :zoom="zoom" :center="center">
      <v-icondefault :image-path="'/statics/leafletImages/'"></v-icondefault>
      <v-tilelayer :url="url"></v-tilelayer>
      <!-- <v-marker-cluster> -->
        <v-marker :lat-lng="marker">
          <v-popup content="test content"></v-popup>
        </v-marker>
      <!-- </v-marker-cluster> -->
    </v-map>
  </div>
</template>
<script>
import Vue from 'vue'
import { mapState, mapGetters } from 'vuex'
import store from '@/store/'
import L from 'leaflet'
import leafletCss from 'leaflet-css'
import { LMap, LTileLayer, LMarker, LLayerGroup, LFeatureGroup, LIconDefault, LPopup } from 'vue2-leaflet'
import Vue2LeafletMarkerCluster from 'vue2-leaflet-markercluster'

export default {
  components: {
    'v-map': LMap,
    'v-icondefault': LIconDefault,
    'v-tilelayer': LTileLayer,
    'v-marker': LMarker,
    'v-popup': LPopup
    // 'v-marker-cluster': Vue2LeafletMarkerCluster
  },
  data () {
    return {
      windowHeight: '0',
      windowWidth: '0',
      zoom: store.state.mapStartZoom,
      center: L.latLng(store.state.mapStartLat, store.state.mapStartLng),
      url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      marker: L.latLng(store.state.mapStartLat, store.state.mapStartLng)
    }
  },
  computed: {
    ...mapGetters([
      'getIsMobile',
      'getHostsFiltered',
      'getHosts'
    ]),
    mapStyle () {
      var multiplier = 1
      if (!this.getIsMobile) {
        multiplier = 0.4
      }
      // size to the right height and width on load
      return 'height:' + this.windowHeight + 'px;width:' + (this.windowWidth * multiplier) + 'px; margin:0px; padding: 0px;'
    }
  },
  created () {
    this.$nextTick(() => {
      const map = this.$refs.mymap.mapObject
      const esri = require('esri-leaflet')
      esri.basemapLayer('Topographic').addTo(map)
      window.addEventListener('resize', this.onResize, false) // resize the map on load
      this.windowHeight = window.innerHeight - 105
      this.windowWidth = window.innerWidth
      this.renderComponent = true
      map._onResize() // refresh the changes
    }, (this))
  },
  destroyed () {
    window.removeEventListener('resize', this.onResize)
  },
  methods: {
    onResize () {
      // resize the map when the window is resized
      this.windowHeight = window.innerHeight - 105
      this.windowWidth = window.innerWidth
    },
    getMarkerLatLng (host) {
      // console.log('host', host)
      if (host.lat && host.lon) {
        return L.latLng(host.lat, host.lon)
      }
    },
    getHostsMap () {
      if (store.state.mapShowAllHosts) {
        return this.getHosts
      } else {
        return this.getHostsFiltered
      }
    }
  }
}
</script>