Currently, I am working on a backend API that utilizes a MySQL database. My goal is to extract data from this database and utilize it to plot latitude and longitude points on a map using the Google Maps API. To achieve this, I have integrated the Gmaps API with Nuxt JS.
Despite my efforts, I encountered an error message stating:
"Cannot read properties of undefined (reading 'coordinates')"
The code snippet below showcases my attempt to retrieve data:
async function getData(){
const {data} = await this.$axios.$get('http://localhost:8000/api/parkingPlace');
console.log(data)
return {data}
}
Subsequently, I aim to pass this data into my Gmaps instance.
export default {
data() {
return {
currentLocation: {},
circleOptions: {},
parkingPlaces: getData(),
This data will then be used to fetch and display values for latitude and longitude as pins on the map.
<template>
<div class="min-h-screen relative max-6/6" > ;
<GMap class="absolute inset-0 h-100% bg-blue-400"
ref="gMap"
language="en"
:cluster="{options: {styles: clusterStyle}}"
:center="{lat:parkingPlaces[0].coordinates.lat, lng: parkingPlaces[0].coordinates.lng}"
:options="{fullscreenControl: false, styles: mapStyle}"
:zoom="5">
<GMapMarker
v-for="location in parkingPlaces"
:key="location.id"
:position="{lat: location.coordinates.lat, lng: location.coordinates.lng}"
:options="{icon: location.free_spots > 0 ? pins.spacefree : pins.spacenotfree}"
@click="currentLocation = location"
>
<GMapInfoWindow :options="{maxWidth: 200}">
<code>
lat: {{ location.coordinates.lat }},
lng: {{ location.coordinates.lng }}
</code>
</GMapInfoWindow>
</GMapMarker>
<GMapCircle :options="circleOptions"/>
</GMap>
</div>
</template>
The complete index.vue
script where I attempt to implement this functionality can be found below.
<template>
<div class="min-h-screen relative max-6/6" > ;
<GMap class="absolute inset-0 h-100% bg-blue-400"
ref="gMap"
language="en"
:cluster="{options: {styles: clusterStyle}}"
:center="{lat:parkingPlaces[0].coordinates.lat, lng: parkingPlaces[0].coordinates.lng}"
:options="{fullscreenControl: false, styles: mapStyle}"
:zoom="5">
<GMapMarker
v-for="location in parkingPlaces"
:key="location.id"
:position="{lat: location.coordinates.lat, lng: location.coordinates.lng}"
:options="{icon: location.free_spots > 0 ? pins.spacefree : pins.spacenotfree}"
@click="currentLocation = location"
>
<GMapInfoWindow :options="{maxWidth: 200}">
<code>
lat: {{ location.coordinates.lat }},
lng: {{ location.coordinates.lng }}
</code>
</GMapInfoWindow>
</GMapMarker>
<GMapCircle :options="circleOptions"/>
</GMap>
</div>
</template>
<script>
async function getData(){
const {data} = await this.$axios.$get('http://localhost:8000/api/parkingPlace');
console.log(data)
return {data}
export default {
data() {
return {
currentLocation: {},
circleOptions: {},
parkingPlaces: getData(),
// Dispatched API response example:
// {
// "id": 1,
// "name": "Chandler Larson",
// "post": "37757",
// "coordinates": {
// "lng": -51.84,
// "lat": -60.02
// },
// "total_spots": 0,
// "free_spots": 0
// }
// ],
pins: {
spacefree: "/parkingicongreen3.png",
spacenotfree: "/parkingiconred3.png",
},
mapStyle: [],
clusterStyle: [
{
url: "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m1.png",
width: 56,
height: 56,
textColor: "#fff"
}
]
}
}
}
</script>
I utilized Axios to retrieve data from my database and showcase them on the Google Maps interface.
I anticipate visualizing points on the map based on the latitude and longitude fetched from my database.
EDIT 1:
Modifications were implemented according to @kissu's advice.
<template v-if="parkingPlaces.length > 0">
<div class="min-h-screen relative max-6/6" > ;
<GMap class="absolute inset-0 h-100% bg-blue-400"
ref="gMap"
language="en"
:cluster="{options: {styles: clusterStyle}}"
:center="{lat:this.parkingPlaces[0].coordinates.lat, lng: this.parkingPlaces[0].coordinates.lng}"
:options="{fullscreenControl: false, styles: mapStyle}"
:zoom="5">
<GMapMarker
v-for="location in parkingPlaces"
:key="location.id"
:position="{lat: location.coordinates.lat, lng: location.coordinates.lng}"
:options="{icon: location.free_spots > 0 ? pins.spacefree : pins.spacenotfree}"
@click="currentLocation = location"
>
<GMapInfoWindow :options="{maxWidth: 200}">
<code>
lat: {{ location.coordinates.lat }},
lng: {{ location.coordinates.lng }}
</code>
</GMapInfoWindow>
</GMapMarker>
<GMapCircle :options="circleOptions"/>
</GMap>
</div>
</template>
<script>
// async function getData(){
// const {data} = await this.$axios.$get('http://localhost:8000/api/parkingPlace');
// console.log(data)
// return {data}
// }
export default {
data() {
return {
currentLocation: {},
circleOptions: {},
parkingPlaces: [],
pins: {
spacefree: "/parkingicongreen3.png",
spacenotfree: "/parkingiconred3.png",
},
mapStyle: [],
clusterStyle: [
{
url: "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m1.png",
width: 56,
height: 56,
textColor: "#fff"
}
]
}
},
async fetch(){
this.parkingPlaces = await fetch('http://localhost:8000/api/parkingPlace').then(res => res.json())
console.log(this.parkingPlaces)
}
}
</script>
Check out the output of console.log(this.parkingPlaces)
https://i.sstatic.net/KA7EO.png
EDIT 2