Vue2-leaflet map not showing properly in BoostrapVue modal
There were 3 issues because of which this was happening.
1. First - I forgot to load the leaflet css into main.js
- this is why the leaflet map was somehow outside the modal.
//src/main.jsimport '@babel/polyfill';import Vue from 'vue';import './plugins/bootstrap-vue';import App from './App.vue';import router from './router';import store from './store';//above imports not important to this answerimport 'leaflet/dist/leaflet.css'; //<--------------add this linenew Vue({ router, store, render: h => h(App),}).$mount('#app');
2. Now the map may disappear. Set a width and height on the l-map
component's container. I used a class but you can use style="" etc.
<div class="foobar1"> <!-- <--- Add a class on l-map's container --> <l-map :center="center" :zoom="13"> <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer> <l-marker :lat-lng="center"></l-marker> </l-map></div>
<style lang="scss"> .foobar1 { /* <--- class we added above */ width: 100%; height: 400px; }</style>
3. Now your map will render within the modal but if you move the map's view, you'll see that leaflet does not download the map's squares in time.You will see something like this:
To fix this:
create an event handler on
b-modal
for the@shown
event.<b-modal @shown="modalShown" @hidden="$emit('clear')" size="lg" :visible="visible" title="Event details" >
I called mine
modalShown
.Then, add a
ref
attribute to yourl-map
. I called minemymap
.<l-map :center="center" :zoom="13" ref="mymap"> <!-- ref attribute added to l-map --> <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer> <l-marker :lat-lng="center"></l-marker></l-map>
Then, create a
modalShown
method in the Vue methods for your view/component and callinvalidateSize()
inside.export default { data() { //some data here } methods: { modalShown() { setTimeout(() => { //mapObject is a property that is part of leaflet this.$refs.mymap.mapObject.invalidateSize(); }, 100); } }}
Now everything should be fine:
- map should not spill outside the modal
- map should be visible (duh)
- map squares should be downloaded when within map body
Addtional to Artur Tagisow answer
You can also use this approach to your parent component if your map is in child component.
export default { data() { //some data here } methods: { modalShown() { setTimeout(() => { window.dispatchEvent(new Event("resize")); }, 100); } }}
For vue.js and nuxt.js developers , probably it's because of using v-show or v-if!in your case display none happening by bootstrap modalbut dont worry the only thing u have to do is using client-only (its like ssr but for new version of js frameworks like nuxt or vue):
<client-only><div id="bootstrapModal"><div id="map-wrap" style="height: 100vh"> <l-map :zoom=13 :center="[55.9464418,8.1277591]"> <l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"></l-tile-layer> <l-marker :lat-lng="[55.9464418,8.1277591]"></l-marker> </l-map> </div></div></client-only>
ps: if still not loaded in iphone browsers it's probably because of geolocation