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
    3946
    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.
    • A
      atelier last edited by

      What is the process for adding scripts from CDNs in v0.15.x projects? In particular, I’m trying to add Google Maps. Adding a script tag in index.template.html does not work. Thanks in advance.

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

        You should use a quasar plugin and a promise. quasar new plugin google

        Take a look at this post

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

          After adding a new plugin and creating an externalApi.js file as suggested in that link, I’m getting a dependency not found error. Any idea why this might be?

          1 Reply Last reply Reply Quote 0
          • 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