Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using vuetify-google-autocomplete with vue2-google-maps #60

Closed
romucci opened this issue Oct 31, 2018 · 5 comments
Closed

Using vuetify-google-autocomplete with vue2-google-maps #60

romucci opened this issue Oct 31, 2018 · 5 comments

Comments

@romucci
Copy link

romucci commented Oct 31, 2018

I am having issues setting vuetify-google-autocomplete when I am also using vue2-google-maps, I only use the API key when I load google maps.

Apparently the API is not loading correctly on page refresh :/

VuetifyGoogleAutocomplete.js?2bd5:330 Uncaught TypeError: Cannot read property 'setBounds' of null
@toddb
Copy link

toddb commented Oct 7, 2020

I am just leaving a trail of my findings of the same problem.

There are a number of issues:

  • the immediate issue of setBounds
  • avoiding double loading error messages

My plugin code:

import Vue from 'vue';
import * as VueGoogleMaps from 'vue2-google-maps';

const key = 'xxxxxxxx';

// @see https://www.npmjs.com/package/vue2-google-maps
Vue.use(VueGoogleMaps, {
    load: {
        key: key,
        // This is required to use the Autocomplete plugin
        libraries: 'places', // 'places,drawing,visualization'
    },
});

// @see https://www.npmjs.com/package/vuetify-google-autocomplete
Vue.use(VuetifyGoogleAutocomplete, {
    apiKey: key,    // <-- removing apiKey means that the install code doesn't double load (which is another error)
});

So if you turn off the apiKey, it creates the SetBounds.

This in turn CAN be quietened by turning OFF geolocation. But that removes functionality and masks errors:

             <vuetify-google-autocomplete
                        id="map"
                        :value="searchValue"
                        append-icon="search"
                        :disabled="false"
                        clearable
                        :enable-geolocation="false"  <!-- disabled
                         ...  />

This is implemented:

    geolocate() {
      if (this.enableGeolocation && !this.geolocateSet) {    // turned off means this code path is no longer executed
        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition((position) => {
            const geolocation = {
              lat: position.coords.latitude,
              lng: position.coords.longitude,
            };
            const circle = new window.google.maps.Circle({
              center: geolocation,
              radius: position.coords.accuracy,
            });
            this.autocomplete.setBounds(circle.getBounds());   // autocomplete is null is the original error
            this.geolocateSet = true;
          });
        }
      }
    },

But that means that the autocomplete now no longer works!

Seems that immediate issues are to:

  1. add some error handling/checking code so that it doesn't hard crash
  2. remediate the plugin to allow for lazy/other loaded google code (I haven't investigated this)

Tracking down the loading:

this.autocomplete = new window.google.maps.places.Autocomplete(

  setupGoogle() {
 
 ...

     this.autocomplete = new window.google.maps.places.Autocomplete(
        document.getElementById(this.id),
        options,
      );

So the setup code is not being called because this listener is not triggered.

    'vgaMapState.initMap': function vgaMapStateInitMap(value) {
      if (value) {
        this.setupGoogle();
      }
    },

And that's because in the original init setup code, the callback from google calls code that sets window.vgaMapState.initMap = true as well as from mounted

options.callback = 'initVGAMaps';

window.initVGAMaps = () => {

Setup from mounted:

  mounted() {
    this.vgaMapState = window.vgaMapState;
    // if (Object.prototype.hasOwnProperty.call(window, 'google')
    //   && Object.prototype.hasOwnProperty.call(window, 'maps')) {
    if (Object.prototype.hasOwnProperty.call(window, 'google')) {
      // we've been here before. just need to get Autocomplete loaded
      this.setupGoogle();
    }
  },

@toddb
Copy link

toddb commented Oct 7, 2020

To remove all the errors and not get double loading (and make no code changes). This is not a pleasure.

Remove the plugin registration

import Vue from 'vue';
import * as VueGoogleMaps from 'vue2-google-maps';

const key = 'xxxxxxxxs';

// @see https://www.npmjs.com/package/vue2-google-maps
Vue.use(VueGoogleMaps, {
    load: {
        key: key,
        // This is required to use the Autocomplete plugin
        libraries: 'places', // 'places,drawing,visualization'
    },
});

// NO LONGER GLOBALLY REGISTERED
// @see https://www.npmjs.com/package/vuetify-google-autocomplete
/*
Vue.use(VuetifyGoogleAutocomplete, {
    // apiKey: key,
    // version: '...', // Optional
    // language: '...', // Optional
});
*/

Then in the local component (from my documentation)

        /**
         * A workaround 'timing' function that ensures google is loaded before the 'google-autocomplete' is loaded.
         * This method is called when the gmap component is visible. Currently, this is a workaround to hold off loading
         * the vuetify-google-autocomplete with a skeleton loader until ready
         *
         * Basic design:
         *
         *  - skeleton loader around autocomplete
         *  - v-intersect on gmap triggers callback
         *  - callback that ensures google has loaded via map promise
         *
         * @example
         *
         * Template:
         *   <v-skeleton-loader :loading="loading">
         *       <vuetify-google-autocomplete ... />
         *    </v-skeleton-loader>
         *
         *
         *   <GmapMap
         *       ref="map"
         *       v-intersect.quiet="loaded"
         *       ... />
         *
         * Script:  (ensure you import locally VuetifyGoogleAutocomplete and add to component)
         *
         *   protected loading = true;
         *
         *   private loaded(): void {
         *       this.$refs.map.$mapPromise.then(() => {
         *           this.loading = !Object.prototype.hasOwnProperty.call(window, 'google');
         *       });
         *   }
         *
         *
         *   Notes for typescript
         *
         *    public $refs!: Refs<{ map: { $mapPromise: Promise<void> }; }>;
         *
         *   interfaces.d.ts
         *
         *    type Refs<T extends Record<string, unknown>> = Vue['$refs'] & T;
         *    declare module 'vuetify-google-autocomplete/lib/VuetifyGoogleAutocomplete';
         *        
         * Ideally, this code check could have been in mounted, however, it doesn't work and many have tried.
         *  @see https://stackoverflow.com/questions/54355375/vue-js-refs-are-undefined-even-though-this-refs-shows-theyre
         *
         */

toddb pushed a commit to picmi/vuetify-google-autocomplete that referenced this issue Oct 27, 2020
@toddb toddb mentioned this issue Oct 27, 2020
@toddb
Copy link

toddb commented Oct 27, 2020

@MadimetjaShika any chance of getting that pull request through at some stage?

@MadimetjaShika
Copy link
Owner

#109 Merged and published as v2.0.4. Please re-open if this is still an issue.

@toddb
Copy link

toddb commented Oct 27, 2020

The original error can still occur, sorry :-( (v2.0.4)

There is a race condition if the field has focus too early. The 'autocomplete' field could be behind a promise.

see https://github.com/MadimetjaShika/vuetify-google-autocomplete/blob/dev/src/vga/VuetifyGoogleAutocomplete.js#L925

opened issue #112

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants