Google Maps showing grey box in Vue modal

789 Views Asked by At

I have a <b-modal> from VueBootstrap, inside of which I'm trying to render a <GmapMap> (https://www.npmjs.com/package/gmap-vue)

It's rendering a grey box inside the modal, but outside the modal it renders the map just fine.

All the searching I've done leads to the same solution which I'm finding in some places is google.maps.event.trigger(map, 'resize') which is not working. Apparently, it's no longer part of the API [Source: https://stackoverflow.com/questions/13059034/how-to-use-google-maps-event-triggermap-resize]

<template>
  <div class="text-center">
    <h1>{{ title }}</h1>
    <div class="row d-flex justify-content-center">
      <div class="col-md-8">
        <GmapMap
          ref="topMapRef"
          class="gmap"
          :center="{ lat: 42, lng: 42 }"
          :zoom="7"
          map-type-id="terrain"
        />
        <b-table
          bordered
          dark
          fixed
          hover
          show-empty
          striped
          :busy.sync="isBusy"
          :items="items"
          :fields="fields"
        >
          <template v-slot:cell(actions)="row">
            <b-button
              size="sm"
              @click="info(row.item, row.index, $event.target)"
            >
              Map
            </b-button>
          </template>
        </b-table>

        <b-modal
          :id="mapModal.id"
          :title="mapModal.title"
          @hide="resetInfoModal"
          ok-only
        >
          <GmapMap
            ref="modalMapRef"
            class="gmap"
            :center="{ lat: 42, lng: 42 }"
            :zoom="7"
            map-type-id="terrain"
          />
        </b-modal>
      </div>
    </div>
  </div>
</template>

<script>
// import axios from "axios";
import { gmapApi } from 'gmap-vue';

export default {
  name: "RenderList",
  props: {
    title: String,
  },
  computed: {
    google() {
      return gmapApi();
    },
  },
  updated() {
    console.log(this.$refs.modalMapRef);
    console.log(window.google.maps);


    this.$refs.modalMapRef.$mapPromise.then((map) => {
      map.setCenter(new window.google.maps.LatLng(54, -2));
      map.setZoom(2);
      window.google.maps.event.trigger(map, 'resize');
    })
  },
  data: function () {
    return {
      items: [
        { id: 1, lat: 42, long: 42 },
        { id: 2, lat: 42, long: 42 },
        { id: 3, lat: 42, long: 42 },
      ],
      isBusy: false,
      fields: [
        {
          key: "id",
          sortable: true,
          class: "text-left",
        },
        {
          key: "text",
          sortable: true,
          class: "text-left",
        },
        "lat",
        "long",
        {
          key: "actions",
          label: "Actions"
        }
      ],
      mapModal: {
        id: "map-modal",
        title: "",
        item: ""
      }
    }
  },
  methods: {
    // dataProvider() {
    //   this.isBusy = true;
    //   let promise = axios.get(process.env.VUE_APP_LIST_DATA_SERVICE);

    //   return promise.then((response) => {
    //     this.isBusy = false
    //     return response.data;
    //   }).catch(error => {
    //     this.isBusy = false;
    //     console.log(error);
    //     return [];
    //   })
    // },
    info(item, index, button) {
      this.mapModal.title = `Label: ${item.id}`;
      this.mapModal.item = item;
      this.$root.$emit("bv::show::modal", this.mapModal.id, button);
    },
    resetInfoModal() {
      this.mapModal.title = "";
      this.mapModal.content = "";
    },
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1 {
  margin-bottom: 60px;
}
.gmap {
  width: 100%;
  height: 300px;
  margin-bottom: 60px;
}
</style>

Does anyone know how to get the map to display properly in the modal?

Surely, I'm not the first to try this?

1

There are 1 best solutions below

0
On

Had this problem, in my case it was solved by providing the following options to google maps:

mapOptions: {
        center: { lat: 10.365365, lng: -66.96667 },
        clickableIcons: false,
        streetViewControl: false,
        panControlOptions: false,
        gestureHandling: 'cooperative',
        mapTypeControl: false,
        zoomControlOptions: {
          style: 'SMALL'
        },
        zoom: 14
      }

However you can probably make-do with just center and zoom.

Edit: Try using your own google maps components, follow this tutorial:

https://v2.vuejs.org/v2/cookbook/practical-use-of-scoped-slots.html#Base-Example

You can use the package described in the tutorial to load the map, dont be scared by the big red "deprecated" warning on the npm package page.

However for production, you should use the package referenced by the author, which is the one backed by google:

https://googlemaps.github.io/js-api-loader/index.html

The only big difference between the two: The 'google' object is not returned by the non-deprecated loader, it is instead attached to the window. See my answer here for clarification:

'google' is not defined Using Google Maps JavaScript API Loader

Happy coding!