inocan-group / vue3-google-map

A set of composable components for easy use of Google Maps in your Vue 3 projects.
https://vue3-google-map.com
MIT License
283 stars 57 forks source link

Since v0.5.2 map is no longer shown, no warnings/errors in console #13

Closed maninak closed 3 years ago

maninak commented 3 years ago

Hello,

it seems that there's a regression on v0.5.2. The map isn't rendering any tiles, apparently.

Going back to v0.5.1 the same code renders as expected but, obviously, I won't have the (necessary for me) fix https://github.com/inocan-group/vue3-google-map/pull/11 published in v0.5.2

Expected:

map-expected

Actual:

map-actual

Context:

Here's my (trimmed down) component code:

<template>
  <GoogleMap
    id="map"
    ref="googleMapCmp"
    class="base-map"
    map-type-id="hybrid"
    :api-key="GOOGLE_MAPS_CONFIG.key"
    :region="GOOGLE_MAPS_CONFIG.region"
    :language="GOOGLE_MAPS_CONFIG.language"
    :center="center"
    :zoom="zoom"
    :map-type-control="false"
    :clickable-icons="false"
  >
    <Marker
      v-for="marker in markers"
      :key="marker.name"
      :options="{
        position: marker.position,
        clickable: true,
        icon: {
          url: require('../assets/icons/pin.svg'),
          scaledSize: { width: 50, height: 50 },
        },
        title: marker.name,
      }"
    />
  </GoogleMap>
</template>

<script lang="ts">
import { ComponentPublicInstance, PropType, Ref, computed, defineComponent, ref } from 'vue'
import { GoogleMap, Marker } from 'vue3-google-map'

import { GOOGLE_MAPS_CONFIG } from '../config'
import { GMapsMarker, GMapsPosition } from '../types'

export default defineComponent({
  props: {
    center: { type: Object as PropType<GMapsPosition>, required: true },
    markers: { type: Array as PropType<GMapsMarker[]>, default: [] },
    maxZoom: { type: Number, default: 16 },
  },
  components: {
    GoogleMap,
    Marker,
  },
  setup(props) {
    const googleMapCmp = ref(undefined) as Ref<ComponentPublicInstance | undefined>
    const boundedZoom = ref(7)

    const zoom = computed(() => Math.min(props.maxZoom, boundedZoom.value))

    return {
      googleMapCmp,
      GOOGLE_MAPS_CONFIG,
      center: props.center,
      zoom,
      markers: [
        { name: 'Hello Station', position: { lat: 48.21231609, lng: 16.37369946 } },
        { name: 'schre a fw1', position: { lat: 48.2129584, lng: 16.3796558 } },
        { name: 'schre c fo1 b1', position: { lat: 48.2129584, lng: 16.3796558 } },
        { name: 'haule a fs1', position: { lat: 48.2129584, lng: 16.3796558 } },
        { name: 'bruen c fnw2 b1', position: { lat: 48.136868, lng: 16.469517 } },
        { name: 'bruen b fso2 b2', position: { lat: 48.20629212, lng: 16.36377215 } },
        { name: 'bruen a fso2 b1', position: { lat: 48.22218047, lng: 16.36900497 } },
        { name: 'andau b fno1 b1', position: { lat: 48.045063, lng: 16.583197 } },
        { name: 'andau a fs2 b114445566', position: { lat: 49.3180524, lng: 16.50256704 } },
        { name: 'Test💕', position: { lat: 48.21016003, lng: 16.372449 } },
        { name: 'andau d fso2', position: { lat: 48.16687, lng: 16.256882 } },
        { name: 'GRITSCH - Helix 113/1019', position: { lat: 48.21410127, lng: 16.37249142 } },
      ],
    }
  },
})
</script>

<style lang="scss" scoped>
@import '../styles/constants/_colors.scss';
@import '../styles/utils/_material-shadow';

.base-map {
  @include material-shadow($level: 1, $background: $color-platinum);
  height: 100%;
  border-radius: 4px;

  :deep(.vue-map) {
    border-radius: 4px;
  }
}

#map {
  width: 100%;
  height: 100%;
}
</style>

Additional info:

No errors or warnings in the console

HusamElbashir commented 3 years ago

This is due to the use of the scoped .base-map class. Since v0.5.2 we're painting the map on an internal non-root div of the GoogleMap component. It does receive all the $attrs so it will receive the class defined in the parent but the class won't be applied correctly due to the scoping. You'll need to either qualify the class with a deep selector or use inline styles instead to avoid the scoping:

::v-deep .base-map {
  @include material-shadow($level: 1, $background: $color-platinum);
  height: 100%;
  border-radius: 4px;

  :deep(.vue-map) {
    border-radius: 4px;
  }
}

See the example sandbox from your other issue: https://codesandbox.io/s/unruffled-bas-j8ly8

maninak commented 3 years ago

Got it, thank you for looking into it!

Turns out anything can be a breaking change, right? :)

FYI what you described you're doing ( receiving all the $attrs) had another side-effect of two elements having the id map in my DOM because I was doing <GoogleMap id="map"> and of course the id is part of the $attrs that get copied.

Also my scss code now looks odd because of it too.

.base-map {
  width: 100%;
  height: 100%;
}

// this confusing selector actually targets the lib-generated component that inherits
// (a.k.a has copy-pasted on it) the $attrs of `<GoogleMap>`. Ending up in two distinct components
// having the class `.base-map`
:deep(.base-map) {
  height: 100%;
  border-radius: 4px;
  @include material-shadow($level: 1, $background: $color-platinum);

  .vue-map {
    border-radius: 4px;
  }
}

Nothing I can't live with, just thought you may get some value out of a real-world use case. Thank you!

HusamElbashir commented 3 years ago

Thanks for pointing that out. Apparently we forgot to inheritAttrs: false to prevent the root div from receiving those attrs as well. Will add that in the next release.