[Vue.js 2][Google Places API] How to fix this error : "Uncaught TypeError: Cannot read property 'getPlacePredictions' of null"?

Viewed 501

I would like to receive a boost as I have been stuck on this issue for quite some time. Thank you very much for your precious time.

Goal :

I would like to solve a problem. The problem is this error message in the console:

enter image description here

Results:

On a page where I use it, a redirect is done and redirects me to another page where I use it but I am no longer able to use the tool. It no longer offers me anything and shows me this error above in the console.

However, if I refresh the page (hard reload) or click on another page then click back to the profile settings page, then it works fine.

User flow

When a user signs up, he/she gets to fill a form (on a vue.js component) as part of an "onboarding" flow. On that specific form, the user is asked to add a place (via the v-autocomplete). To do so, I'm using the code (see below) under the script section of that component.

When the user is done, he is redirected to his/her profile settings page (again, another vue.js component) where he/she can again edit the place via the v-autocomplete. To do so, I'm using exactly the the code below(see below)under the script section of that component.

Note. Hence, the app vue.js create twice a google map instance.

My code :

The v-autocomplete :

<v-autocomplete
v-model="userPrefs.prefPlace"
:items="searchResults"
:search-input.sync="location"
hide-no-data
hide-selected
:placeholder="userPrefs.prefPlace"
item-text="Description"
item-value="API"
:error-messages="placeErrors"
@blur="$v.userPrefs.prefPlace.$touch()"
required: true
outlined
></v-autocomplete>

The metaInfo() :

metaInfo() {
  return {
    script: [
      {
        src: `https://maps.googleapis.com/maps/api/js?key=${process.env.VUE_APP_FB_APIKEY}&libraries=places`,
        async: true,
        defer: true,
        callback: () => this.MapsInit() // will declare it in methods
      }
    ]
  };
}

The watch :

watch: {
  location(newValue) {
    this.timeOutID = debounce(() => {
      if (newValue) {
        this.service.getPlacePredictions(
          {
            input: this.location,
            types: ["(regions)"],
            componentRestrictions: { country: "be" }
          },
          this.displaySuggestions
        );
      }
    }, this.timeOutID, 500);
  }
}

The method MapsInit() and displaySuggestions() :

methods: {
  MapsInit() {
    this.service = new window.google.maps.places.AutocompleteService();
  },
  displaySuggestions(predictions, status) {
    if (status !== window.google.maps.places.PlacesServiceStatus.OK) {
      this.searchResults = [];
      return;
    }
    this.searchResults = predictions.map(prediction => prediction.description);
  }
};

So, would you know where the problem is coming from? If you are missing anything, please let me know, thank you!

1 Answers

The problem seems to be the Google Places script is not loaded (via the meta callback to MapsInit()) by the time the location watcher is called, so this.service is still its initial value (null).

One option is to load the script earlier in the app's lifecycle (e.g., in the App component, or within the head tag of index.html).

Another option is to conditionally render the v-autocomplete based on service so that the location watcher is only called when service is actually set:

<v-autocomplete v-if="service" :search-input.sync="location">

This assumes <v-autocomplete> is the only source of change to location.

Related