No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Google Maps from CDN problem

    Help
    3
    19
    3410
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • a47ae
      a47ae last edited by

      Please also tell us which dependency could not be found.
      Paste your plugin file here and also the error message.

      If you are only interested in loading Google Maps, you could also take a look at https://github.com/Akryum/vue-googlemaps

      This uses a very similar aproach to load the libary like @benoitranque took, but with the added benefit that it wraps the maps API in Vue components.
      To use this you would first run yarn add vue-googlemaps to add the dependencies.
      Then create a new Quasar plugin with quasar new plugin maps.
      In the newly generated file add the following (make shure to add your api key:

      import 'vue-googlemaps/dist/vue-googlemaps.css'
      import VueGoogleMaps from 'vue-googlemaps'
      
      export default ({ app, router, Vue }) => {
        Vue.use(VueGoogleMaps, {
        load: {
          apiKey: 'your-google-api-key',
          libraries: ['places'],
        },
      })
      }
      
      

      Now in your components you can use the <googlemaps-*> components to create your map:

      <googlemaps-map
        :center.sync="center"
        :zoom.sync="zoom"
        :options="mapOptions"
        @idle="onIdle"
        @click="onMapClick">
      
        <!-- User Position -->
        <googlemaps-user-position
          @update:position="setUserPosition"
        />
      
        <googlemaps-marker
          v-for="marker of markers"
          :key="marker._id"
          :label="{
            color: marker === currentmarker ? 'white' : 'black',
            fontFamily: 'Material Icons',
            fontSize: '20px',
            text: 'star_rate',
          }"
          :position="marker.position"
          @click="selectMarker(marker._id)"
        />
      </googlemaps-map>
      

      If you are interested, take a look at https://github.com/Akryum/vue-googlemaps/blob/master/src/lib-loader.js
      This is the code to laod the lib. You will notice, it is very similar to @benoitranque solution.
      When the load function is run, a new <script> tag gets created which is then populated with the needed information and appended to the window object.

      1 Reply Last reply Reply Quote 0
      • A
        atelier last edited by

        @a47ae Thanks for your reply. I’m familiar with the Vue Google Maps components, but I don’t think that approach will work for my use case as I’m needing to integrate custom map code from Algolia.

        As @benoitranque suggested, I created an externalApi.js file which includes the code from his post. I then created a new plugin called ‘google’ and registered it with Quasar. This plugin uses the import command as referenced in the ‘main.js’ section of his post. This causes the dependency error. Quasar can’t find externalApi. Being relatively new to Quasar/Vue, I’m probably just overlooking something.

        This is frustrating because I can include the script in the index.html file of a stock Vue installation and it works fine. It would be helpful if Quasar behaved in a similar way.

        1 Reply Last reply Reply Quote 0
        • benoitranque
          benoitranque last edited by

          let me write up a newer version or this, self contained, for use in 0.15

          1 Reply Last reply Reply Quote 0
          • a47ae
            a47ae last edited by

            @atelier Sure you can’t use this? You can pass whatever Google Maps option you need as a prop named options to <GoogleMapsMap> So you could fetch the options from algolia and jsut pass them. 🙂

            See this line in the src: https://github.com/Akryum/vue-googlemaps/blob/master/src/components/Map.vue#L126

            @benoitranque Nice! During my eesarch for solutions I found react-load-script
            Maybee you could create something similar for Vue.js or even as QLoadScript component? 😃
            Should be relative straightforward for your current code.

            1 Reply Last reply Reply Quote 0
            • benoitranque
              benoitranque last edited by

              @a47ae yeah the idea was an async loadscript util. So if you have a large app and say use google maps in only one page, you only want to load google api when that page is visited.
              @atelier here is a v0.15 plugin

              // import something here
              
              // leave the export, even if you don't use it
              export default ({ app, router, Vue }) => {
                // something to do
                let 
                  id = 'google-cdn' // must be unique
                  url = 'https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxxxxxxxxxxx'
              
              
                /*
                 Usage in component
                  
                  async mounted () {
                    await this.$google
                    // google now loaded
                  }
                  
                 Alternative 
              
                  methods {
                    async initGmaps () {
                      await this.$google
                      // google now loaded
                    }
                  }
                 */
              
                this.$google = new Promise((resolve, reject) => {
                  if (document.getElementById(id)) {
                    console.error(`Error loading ${url} async: ${id} is not unique`)
                    return
                  }
                  let script = document.createElement('script')
                  script.src = url
                  script.async = true
                  script.id = id
                  script.onload = () => {
                    resolve()
                  }
                  script.onerror = (err) => {
                    reject(err)
                  }
                  document.body.appendChild(script)
                })
              }
              
              1 Reply Last reply Reply Quote 1
              • A
                atelier last edited by

                @benoitranque This is still not working. I added your code to a new plugin and registered it with Quasar, however I’m getting undefined errors for ‘google’ and ‘map’ when loading the page with the Algolia code.

                I don’t know if this will be of any help, but here is the code I’m trying to implement:

                https://www.algolia.com/doc/tutorials/geo-search/displaying-results-in-google-map/

                I really appreciate your efforts in helping to resolve this.

                1 Reply Last reply Reply Quote 0
                • benoitranque
                  benoitranque last edited by benoitranque

                  After implementation of my code, use this is any component:

                      async mounted () {
                        await this.$google
                        // google now loaded
                        console.log(google)
                      }
                  

                  edit: please confirm whether google is loading properly using this

                  then use the native google maps implementation

                  1 Reply Last reply Reply Quote 0
                  • A
                    atelier last edited by

                    I tried it in a couple different components and I’m getting a ‘google’ is not defined error.

                    1 Reply Last reply Reply Quote 0
                    • benoitranque
                      benoitranque last edited by benoitranque

                      Couple errors on my side, apologies. This should work

                      // import something here
                      var promise = null
                      // leave the export, even if you don't use it
                      export default ({ app, router, Vue }) => {
                        // something to do
                        let 
                          id = 'google-cdn' // must be unique
                          url = 'https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxxxxxxxxxxx'
                      
                      
                        /*
                         Usage in component
                          
                          async mounted () {
                            await this.$google()
                            // google now loaded
                          }
                          
                         Alternative 
                      
                          methods {
                            async initGmaps () {
                              await this.$google()
                              // google now loaded
                            }
                          }
                         */
                      
                        Vue.prototype.$google = function () {
                          if (!promise) {
                            promise = new Promise((resolve, reject) => {
                              if (document.getElementById(id)) {
                                console.error(`Error loading ${url} async: ${id} is not unique`)
                                return
                              }
                              let script = document.createElement('script')
                              script.src = url
                              script.async = true
                              script.id = id
                              script.onload = () => {
                                resolve()
                              }
                              script.onerror = (err) => {
                                reject(err)
                              }
                              document.body.appendChild(script)
                            })
                          }
                          return promise
                        }
                      }
                      

                      edited…

                      1 Reply Last reply Reply Quote 0
                      • A
                        atelier last edited by

                        No luck. I’m still getting ‘google’ not defined error. FYI, I did have to add ‘let =’ before url to define that variable. Not sure if that is affecting your logic.

                        1 Reply Last reply Reply Quote 0
                        • A
                          atelier last edited by

                          Am I supposed to change ‘google-cdn’ with some other value?

                          1 Reply Last reply Reply Quote 0
                          • a47ae
                            a47ae last edited by

                            I just checked from a brand new Quasar project and @benoitranque solution works fine.
                            You first have to create a file src/plugins/maps.js (or run quasar new plugin maps) and add the following:

                            let promise = null
                            
                            export default ({ app, router, Vue }) => {
                              let
                                id = 'google-cdn',
                                url = 'https://maps.googleapis.com/maps/api/js?key=<add-your-key-here>'
                            
                              Vue.prototype.$google = function () {
                                if (!promise) {
                                  promise = new Promise((resolve, reject) => {
                                    if (document.getElementById(id)) {
                                      console.error(`Error loading ${url} async: ${id} is not unique`)
                                      return
                                    }
                                    let script = document.createElement('script')
                                    script.src = url
                                    script.async = true
                                    script.id = id
                                    script.onload = () => {
                                      resolve()
                                    }
                                    script.onerror = (err) => {
                                      reject(err)
                                    }
                                    document.body.appendChild(script)
                                  })
                                }
                                return promise
                              }
                            }
                            
                            

                            Then add 'maps' to the plugins array in quasar.conf.js

                            After that edit the src/pages/index.vue and add the following:

                            <template>
                              <q-page class="flex flex-center">
                                <div id="map"></div>
                              </q-page>
                            </template>
                            
                            <style>
                            #map {
                              height: 400px;
                              width: 90%;
                            }
                            </style>
                            
                            <script>
                            export default {
                              name: 'PageIndex',
                            
                              data () {
                                return {
                                  map: null
                                }
                              },
                            
                              methods: {
                                initMap () {
                                  this.map = new window.google.maps.Map(document.getElementById('map'), {
                                    center: {lat: -34.397, lng: 150.644},
                                    zoom: 8
                                  })
                                }
                              },
                            
                              async mounted () {
                                await this.$google()
                                this.initMap()
                              }
                            }
                            </script>
                            
                            

                            Now if you run quasar run dev the browser should open and after a while you should see a map.

                            If this does not work for you I can also send you the source files.
                            From there it should be easy to adapt the Algolia tutorial. 🙂

                            1 Reply Last reply Reply Quote 2
                            • A
                              atelier last edited by

                              @a47ae I was able to display a map with the code you provided, but I’m unable to get the Algolia code to work without errors. I’m sure the problem is tied to my limited coding skills. I’ll see if I can figure it out otherwise I may have to resort to a stock Vue approach. Thanks so much to you and @benoitranque for all your help. I really appreciate the effort. I don’t want to waste any more of your time on this.

                              1 Reply Last reply Reply Quote 0
                              • a47ae
                                a47ae last edited by

                                Yeah the Algolia stuff is a bit tricky because the tutorial is intended for plain websites and not Vue.js applications.

                                You may wan to take a look at https://community.algolia.com/vue-instantsearch/ which is the official instantsearch plugin for Vue.js

                                To be honest I don’t think that it is easier in plain Vue.js, because Quasar is not really different than a plain Vue.js app.

                                If you have concrete questions do not hesitate to ask them, we are always glad to help. 🙂

                                1 Reply Last reply Reply Quote 0
                                • A
                                  atelier last edited by

                                  The frustrating thing is that the Algolia code works fine on a stock Vue installation after adding the Google API script to the index.html file. It also works great in a Nuxt installation. In fact, Nuxt has a very elegant way of adding external dependencies through its config file. Would love to see something like that for Quasar!

                                  1 Reply Last reply Reply Quote 0
                                  • a47ae
                                    a47ae last edited by

                                    That is strange, If it works in a project generated by vue-cli it almost definitely should work in Quasar without much adaptations.
                                    The only difference is how you load the libraries (btw. also in plain Vue.js it is not recommended to load libraries by adding a script tag, because then you load this library on every page).

                                    If you want post your code and I can take a look at it when I have some spare time. 🙂

                                    1 Reply Last reply Reply Quote 0
                                    • First post
                                      Last post