Nishant S Vispute
Nishant S Vispute

Reputation: 765

How do i update my mapbox markers when the geojson data is passed in as props in a vue component

Edit 1

Here is the source code on git

I am working on an Ionic-Vue project with Mapbox integration. My issue is that I am unable to update my geojson data source to create markers on the map, the geoJson data is passed in as props. Here is the flow

On APP.vue created hook

  1. Using capacitor gets user current location.
  2. .then() make an Axios call to the server to fetch the JSON data
    • On success set the data to store via mutation

On Home.vue[parent component for TheMap.vue]

  1. Computed value called getGeoJson which calls the getters to get geojson data from the state saved an earlier step
  2. Bind the :marker prop with computed value getGeoJson data on the TheMap component to be sent as a prop.
  3. Listen to the event $updatedLocation and call the API action to fetch new geojson data.

On TheMap.vue

  1. On create Hook call the createMap().
  2. In Method: createMap()
    • Get the user coords again using capacitorJS
    • init the mapbox map and save it to this.map variable
    • add Attribution using this.map.addControl
    • this.map.on("load",cb) inside of cb call .addSource() & then addMarkers()
    • Create a new marker for the current user and save it to cosnt UserLocationMarker
    • UserLocationMarker.on("dragend",CB) to emit a event with latest current user location

Here is the code for the same just putting the script tags rather than the whole.vue file

APP.Vue

export default {
  name: "App",
  data() {
    return {
      currentLocation: "",
    };
  },
  created() {
    Geolocation.getCurrentPosition()
      .then((result) => {
        this.currentLocation = [
          result.coords.longitude,
          result.coords.latitude,
        ];
        this.$store.dispatch(
          `lists/${POST_GEOJSON_ACTION}`,
          this.currentLocation
        );
      })
      .catch((err) => console.log(err));
  },
};

Home.vue

<template>
   <the-map :markers="geojson" @updatedLocation="updateMap"></the-map>
</template>
<script>
export default {
  name: "Home",
  computed: {
    getGeoJson() {
      return this.$store.getters[`lists/${GET_GEOJSON_GETTER}`];
    },
  },
  methods: {
    updateMap(center) {
      this.$store.dispatch(`lists/${POST_GEOJSON_ACTION}`, center);
    },
  },
};

</script>

TheMap.vue

export default {
  props: ["markers"],
  emits: ["updatedLocation"],
  data() {
    return {
      access_token: process.env.VUE_APP_MAP_ACCESS_TOKEN,
      center: [0, 0],
      map: {},
    };
  },
  mounted() {
    this.createMap();
  },
  methods: {
    async createMap() {
      try {
        const coords = await Geolocation.getCurrentPosition();
        this.center = [coords.coords.longitude, coords.coords.latitude];
        mapboxgl.accessToken = this.access_token;

        //Map Instance
        this.map = new mapboxgl.Map({
          container: "map",
          style: "mapbox://styles/userName/API_KEY",
          center: this.center,
          zoom: 12,
          scrollZoom: true,
        });

        // Custom Attribution over the map for Branding
        this.map.addControl(
          new mapboxgl.AttributionControl({
            customAttribution: ` &#169; Comapny Name`,
          })
        );

        this.map.on("load", function(e) {
          this.map.addSource("places", {
            type: "geojson",
            data: this.markers,
          });
          this.addMarkers();
        });

        const UserLocationMarker = new mapboxgl.Marker({
          draggable: true,
        })
          .setLngLat(this.center)
          .addTo(this.map);

        UserLocationMarker.on("dragend", async (e) => {
          this.center = Object.values(e.target.getLngLat());
          this.$emit("updatedLocation", this.center);
        });
      } catch (err) {
        console.log(err);
      }
    },

    addMarkers() {
      this.markers.features.forEach(function(marker) {
        var el = document.createElement("div");
        el.id = "marker-" + marker.properties.id;
        el.className = "marker";
        new mapboxgl.Marker(el, { offset: [0, -23] })
          .setLngLat(marker.geometry.coordinates)
          .addTo(this.map);
      });
    },
  },
};

My issue here is that the TheMap.vue does get undefined | [{geojson}] as a prop however it does not load the marker on init or even after the source is changed in the parent component.

What I expect is that the map on Load uses markers prop to build a list of markers if available else show nothing[handle undefined | null`] And update that marker list if a new set of Data is injected as prop on changed location.

Upvotes: 1

Views: 781

Answers (0)

Related Questions