Reputation: 31
This is my code below to fetch API in Nuxt.Js. I have written the code that should be used to call an API, but I am not getting the results. I am not getting any resources regarding this as well.
async created(){
const config = {
headers : {
Accept : "application/json"
}
};
try{
const result = await axios.get(`https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap`, config);
console.warn(result);
//this.users = result.data;
}
catch (err){
console.warn(err);
}
},
Upvotes: 3
Views: 4168
Reputation: 11306
There's an official npm loader for the Google Maps JS API:
https://developers.google.com/maps/documentation/javascript/overview#Loading_the_Maps_API
https://www.npmjs.com/package/@googlemaps/js-api-loader
Below is how I have it implemented in Nuxt (2.15.7).
Side note: Yes, this places your API key client side, which in some contexts (e.g. internal team tools) is fine. For public production deployment, you probably want to protect the API key behind a proxy server, and keep any communication with Google occurring only on your server. A proxy server works great for things like Google search and geolocation services, however for map tiles you may never have a map tile server as fast as Google, so you may have to keep an API key on client-side to ensure smooth performance.
npm i @googlemaps/js-api-loader
plugins/mapGoogle.client.js
This keeps the Google Map API as a global so you can make use of it in various components (i.e. non-map contexts, like searching Google Places in a form).
import Vue from 'vue'
import { Loader } from '@googlemaps/js-api-loader'
// Store GM_instance as a window object (outside of the Vue context) to satisfy the GM plugin.
window.GM_instance = new Loader({
apiKey: process.env.GOOGLEMAPSAPIKEY, // This must be set in nuxt.config.js
version: "weekly",
libraries: ["places", "drawing", "geometry"] // Optional GM libraries to load
})
Vue.mixin({
data() {
return {
GM_loaded: false, // Tracks whether already GM loaded
GM_instance: null, // Holds the GM instance in the context of Vue; much more convenient to use *anywhere* (Vue templates or scripts) whereas directly accessing the window object within Vue can be problematic.
GM_placeService: null, // Optional - Holds the GM Places service
}
},
methods: {
GM_load() {
return new Promise( async (resolve, reject) => {
// Need to do this only once
if (!this.GM_loaded) {
// Load the GM instance
window.GM_instance.load()
.then((response) => {
this.GM_loaded = true
// this.GM_instance is what we use to interact with GM throughout the Nuxt app
this.GM_instance = response
resolve()
})
.catch(e => {
reject(e)
})
} else {
resolve()
}
})
},
// OPTIONAL FUNCTIONS:
GM_loadPlaceService(map) {
this.GM_placeService = new this.GM_instance.maps.places.PlacesService(map)
},
GM_getPlaceDetails(placeRequest) {
return new Promise((resolve, reject) => {
this.GM_placeService.getDetails(placeRequest, (response) => {
resolve(response)
})
})
}
}
})
nuxt.config.js
Pass your GM key from your .env file and register your new plugin.
export default {
// ...
// It's best to keep your GM key where all other keys are: your .env file; however this is inaccessible client-side.
// Here, we tell Nuxt the specific env's we want to make available client-side.
env: {
GOOGLEMAPSAPIKEY: process.env.GOOGLEMAPSAPIKEY
},
// Register your new plugin
plugins: [
'@/plugins/mapGoogle.client.js',
],
// ...
}
components/map.vue
Make a map and process clicks on Google Places
<template>
<div id="map" class="map"></div>
</template>
<script>
export default {
name: "MapGoogle",
data() {
return {
map: null
}
},
mounted() {
// This is the actual trigger that loads GM dynamically.
// Here we run our global GM func: GM_load.
// Side note; annoyance: As you see, using Vue mixin's, you have functions available from out-of-nowhere. Research alternative to mixin's, especially in Vue3/Nuxt3.
this.GM_load()
.then( () => {
this.initMap()
})
},
methods: {
initMap() {
this.map = new this.GM_instance.maps.Map(document.getElementById("map"), {
center: { lat: 43.682284, lng: -79.401603 },
zoom: 8,
})
this.GM_loadPlaceService(this.map)
this.map.addListener("click", (e) => {
this.processClick(e)
})
}
},
async processClick(e) {
// If clicked target has a placeId, user has clicked a GM place
if (e.placeId) {
let placeRequest = {
placeId: e.placeId,
//fields: ['name', 'rating', 'formatted_phone_number', 'geometry']
}
// Get place details
let googlePlace = await this.GM_getPlaceDetails(placeRequest)
console.log("googlePlace %O", googlePlace)
}
}
}
</script>
Upvotes: 5