To address the issue of the Google Maps not rendering in your Livewire component, there are a few steps you can take to ensure everything is set up correctly. Here are some potential solutions and improvements:
-
Ensure the Google Maps API Key is Correct and Enabled: Make sure your Google Maps API key has the necessary permissions for the Maps JavaScript API and Places API.
-
Check the HTML Structure: Ensure that the
#mapdiv has a defined height and width. Without these, the map might not render correctly. -
Load the Google Maps Script Correctly: Ensure the Google Maps script is loaded before your
maps.jsscript. You can do this by including the script in yourmap-component.blade.phpfile. -
Initialize the Map After the Component is Rendered: Ensure that the map initialization code runs after the Livewire component is fully rendered. You can use Livewire's
hookto achieve this.
Here is a revised version of your code with these considerations:
map-component.blade.php
<div>
<div class="place-autocomplete-card" id="place-autocomplete-card">
<p>Search for a place here:</p>
</div>
<div id="map" style="height: 500px; width: 100%;"></div>
<!-- Load Google Maps Script -->
<script>
(g => {
var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__",
m = document, b = window;
b = b[c] || (b[c] = {});
var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams,
u = () => h || (h = new Promise(async (f, n) => {
await (a = m.createElement("script"));
e.set("libraries", [...r] + "");
for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]);
e.set("callback", c + ".maps." + q);
a.src = `https://maps.${c}apis.com/maps/api/js?` + e;
d[q] = f;
a.onerror = () => h = n(Error(p + " could not load."));
a.nonce = m.querySelector("script[nonce]")?.nonce || "";
m.head.append(a)
}));
d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))
})
({key: "{{ env('GOOGLE_MAPS_API_KEY') }}", v: "beta"});
</script>
<!-- Initialize Map after Livewire Component is Rendered -->
<script>
document.addEventListener('livewire:load', function () {
initMap();
});
</script>
</div>
maps.js
let map;
let marker;
let infoWindow;
async function initMap() {
// Request needed libraries.
const [{Map}, {AdvancedMarkerElement}] = await Promise.all([
google.maps.importLibrary("marker"),
google.maps.importLibrary("places"),
]);
// Initialize the map.
map = new google.maps.Map(document.getElementById("map"), {
center: {lat: 35.6764, lng: 139.6500},
zoom: 6,
mapId: "4504f8b37365c3d0",
mapTypeControl: false,
});
const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement({
componentRestrictions: {country: ['jp']},
locationRestriction: map.getBounds(),
});
placeAutocomplete.id = "place-autocomplete-input";
const card = document.getElementById("place-autocomplete-card");
card.appendChild(placeAutocomplete);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
// Create the marker and infowindow
marker = new google.maps.marker.AdvancedMarkerElement({
map,
});
infoWindow = new google.maps.InfoWindow({});
// Add the gmp-placeselect listener, and display the results on the map.
placeAutocomplete.addEventListener("gmp-placeselect", async ({place}) => {
await place.fetchFields({
fields: ["displayName", "formattedAddress", "location"],
});
// If the place has a geometry, then present it on a map.
if (place.viewport) {
map.fitBounds(place.viewport);
} else {
map.setCenter(place.location);
map.setZoom(17);
}
let content =
'<div id="infowindow-content">' +
'<span id="place-displayname" class="title">' +
place.displayName +
"</span><br />" +
'<span id="place-address">' +
place.formattedAddress +
"</span>" +
"</div>";
updateInfoWindow(content, place.location);
marker.position = place.location;
});
// Add listener to update bounds when they change
map.addListener('bounds_changed', () => {
placeAutocomplete.locationRestriction = map.getBounds();
});
}
// Helper function to create an info window.
function updateInfoWindow(content, center) {
infoWindow.setContent(content);
infoWindow.setPosition(center);
infoWindow.open({
map,
anchor: marker,
shouldFocus: false,
});
}
event-create.blade.php
<form id="create" wire:submit.prevent="save" class="space-y-12">
<!-- form contents etc -->
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:py-6">
<label for="form.location" class="block text-sm font-medium text-gray-900 sm:pt-2">Location</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<input type="text" name="form.location" id="form.location" autocomplete="form.location"
wire:model.blur="form.location"
class="block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
@error('form.location')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<livewire:map-component/>
</div>
<!-- form contents etc -->
</form>
app.js
Ensure that maps.js is imported in your app.js if you are using a module bundler like Vite.
import './maps';
By ensuring the map container has a defined height and width, loading the Google Maps script correctly, and initializing the map after the Livewire component is rendered, you should be able to get the map to display correctly.