I am making use of the "vue2-google-maps" package in an application developed with Laravel 5.7. In this case I am creating a component named google-map . Within this component gmap-autocomplete and gmap-map are used . The component is registered in app.js and both the map and the autocomplete input work correctly. The problem is that the input is located above the map and what I want is for it to be inside the map.
I am currently achieving this:
I want it to look like the following image:
This would normally be achieved (without using vue or that package) with the following lines:
let inputSearch = document.getElementById('pac-input');
searchBoxAdd = new google.maps.places.SearchBox(inputSearch );
myMap.controls[google.maps.ControlPosition.TOP_CENTER].push(searchBoxAdd );
But in this case it is not the same. Based on the documentation, I saw that I can access the "map" object by adding ref="mapRef"
it to my gmap-map component and adding
mounted () {
this.$refs.mapRef.$mapPromise.then((map) => {
// En este punto ya tengo mi objeto map.
})
}
Based on this information I tried to do the following:
mounted () {
this.$refs.mapRef.$mapPromise.then((map) => {
let inputSearch = document.getElementById('pac-input');
searchBoxAdd = new google.maps.places.SearchBox(inputSearch );
map.controls[google.maps.ControlPosition.TOP_CENTER].push(searchBoxAdd );
})
But it still does not load the input inside the map and in the console it shows me the following error:
controls.js:118 Uncaught (in promise) TypeError: Cannot read property 'zIndex' of undefined
I leave my main component, which would be "google-maps"
<template>
<div>
<div>
<h2>Search and add a marker</h2>
<label>
<div class="form-inline">
<gmap-autocomplete
class="form-control"
@place_changed="setPlace">
</gmap-autocomplete>
<button @click="addMarker" class="btn btn-primary btn-flat">Add</button>
</div>
</label>
<br/>
</div>
<br>
<gmap-map ref="mapRef"
:center="center"
:zoom="12"
style="width:100%; height: 400px;"
>
<gmap-marker
:key="index"
v-for="(m, index) in markers"
:position="m.position"
@click="center=m.position"
></gmap-marker>
</gmap-map>
</div>
</template>
<script>
import {gmapApi} from 'vue2-google-maps';
export default {
name: "GoogleMap",
data() {
return {
// default to Montreal to keep it simple
// change this to whatever makes sense
center: { lat: 45.508, lng: -73.587 },
markers: [],
places: [],
currentPlace: null
};
},
mounted() {
this.geolocate();
},
methods: {
// receives a place object via the autocomplete component
setPlace(place) {
this.currentPlace = place;
},
addMarker() {
if (this.currentPlace) {
const marker = {
lat: this.currentPlace.geometry.location.lat(),
lng: this.currentPlace.geometry.location.lng()
};
this.markers.push({ position: marker });
this.places.push(this.currentPlace);
this.center = marker;
this.currentPlace = null;
}
},
geolocate: function() {
navigator.geolocation.getCurrentPosition(position => {
this.center = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
});
}
}
};
</script>
Thanks. Cheers!
I already managed to solve it, I did it with the following steps:
Add
ref="mapRef"
to the gmap-map tag . With this later I will be able to access the "map" object. The label should look like this:My control is as follows:
The "parent" div with the "hide" class is important, otherwise the input will be displayed on the page before the map finishes loading and then moved inside. With this, when it is ready the map shows it inside directly. The rest are already styles...
I'm going to add an extra setting to hide mapTypeControl . This is NOT required.
Once the component is mounted, that is, in the "
mounted()
" event, I will use the "map" object to add my component. The code should be like this:Once all this is done, I get the following output:
I hope this helps someone. Cheers!
According to the documentation (and in javascript in general), when you instantiate a new Searchbox what you get is the instance of the "class" (in this case an object).
On the contrary, when you push something,
map.controls[<ubicación>]
what google maps expects is an HTMLElement. It means you could try with:If that doesn't work, I would try to catch the first event
map_idle
before manipulating the DOM of the map container.