Calling Alpine.js methods from third-party scripts
How we made Alpine-powered page understand Google Map events
Recently, we faced a small challenge when implementing Google Map on an Alpine.js powered page. Key points:
- Map markers data is loaded in the Alpine.js store
- The Google Map is outside the Alpine.js scope so cannot call Alpine method directly after its loaded
There was no way we could show those map markers on the Google Map.
After some surfing, this thread gave a hint. Let us go through the actual code to set up the base.
Google Maps related code
<div class="container">
<div id="google-map" style="height: 600px;"></div>
</div>
...
<script async src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=renderMap"></script>
<script>
var googleMapObject;
function renderMap() {
googleMapObject = new google.maps.Map(document.getElementById("google-map"), {
// Map config
});
}
</script>
And here's the Alpine.js setup code
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('app', {
mapMarkers: [
// Pre-loaded markers data
]
});
});
</script>
Solution
Events to the rescue. You can just fire a custom Javascript window event from the Google Maps object and make Alpine listen to it. Let's see the code:
<script>
function renderMap() {
// initialize map code
var mapLoadedEvent = new Event('map-loaded');
window.dispatchEvent(mapLoadedEvent);
}
</script>
First, we are firing the custom JS event called map-loaded
once the Google Map is loaded.
<div class="container" x-data @map-loaded.window="$store.app.addAllMarkers()">
<div id="google-map" style="height: 600px;"></div>
</div>
This HTML code listens to that event and calls the addAllMarkers Alpine method. With that, our Google Map can call the Alpine.js method to show the map markers.
Lastly, our Alpine method can do the rest.
<script>
var googleMapObject;
document.addEventListener('alpine:init', () => {
Alpine.store('app', {
mapMarkers: [
// Pre-loaded markers data
],
addAllMarkers() {
this.mapMarkers.forEach(function (mapMarker) {
new google.maps.Marker({
// Map marker config
});
});
},
});
});
</script>
We did this for Google Maps but you can do the same with any other third-party JS library using the custom Javascript window event.
Important to Note that a
CustomEvent
is different from a regular JSEvent
. Check this Stackoverflow answer for details.
Cheers!