Ridermansb / vue-gmaps

Search places and address using Google Maps API
https://ridermansb.github.io/vue-gmaps
GNU Affero General Public License v3.0
117 stars 13 forks source link

setting v-model #5

Open Youdaman opened 7 years ago

Youdaman commented 7 years ago

I noticed that if you don't specify a v-model attribute, the value of the search field to changes to whatever you pick from the autocomplete, but if you do have a v-model it remains what you typed.

e.g. if you type "adriat" and pick "Adriatic Sea" from the autocomplete, and you have a v-model attribute, then the field value remains "adriat".

If you don't specify a v-model the field value changes to be whatever you picked.

I overcame this by watching the v-gmaps-searchbox object and then setting the v-model of the field to be the value of its place.formatted_address field:

Here's my input with the v-model specified:

        <input class="input" v-model="location.search" v-gmaps-searchbox="location" placeholder="">

Here's the corresponding data field:

    data: function() {
      return {
        location: { search: '' }
      }
    }

Then here's the watch function:

    watch: {
      location: function() {
        this.location.search = this.location.place.formatted_address
      }
    }

This sets the v-model appropriately however it'd be cooler if the autocomplete set it automatically upon selection.

However, this doesn't work if you don't select one of the autocomplete options, i.e. if you just hit enter on your keyboard after typing a term, and doesn't seem to work for subsequent autocomplete selections.

To make it work as expected I had to do a deep watch:

      location: {
        handler: function (val, oldVal) {
          console.log('location', this.location)
          if (this.location.place) {
            this.location.search = this.location.place.formatted_address
          }
        },
        deep: true
      },

One caveat is that that console.log line will get printed every new character you type because the search term is part of the location object. To avoid this (in case you're calling a more expensive operation than logging) you can move the search term model outside the location object, e.g.

 location: {},
 search: ''

and then in the watch handler have instead:

            this.search = this.location.place.formatted_address

Alternatively you could use some kind of debounce method.

Youdaman commented 7 years ago

Actually, instead of this.location.place.formatted_address it might be preferable to use this.location.place.name for things like businesses or landmarks etc.

Or you could use both like "name, address":

            this.search = this.location.place.name
            if (this.location.place.name != this.location.place.formatted_address) {
              this.search += ', ' + this.location.place.formatted_address
            }

Or better still, in cases where the address begins with the name (like Danube River, where the start of the formatted_address is "Danube River" so you end up with "Danube River, Danube River, Donaueschingen, Germany"):

            if (this.location.place.formatted_address.indexOf(this.location.place.name) == 0) {
              this.search = this.location.place.formatted_address
            } else {
              this.search += ', ' + this.location.place.formatted_address
            }

The check to see if name and formatted_address are the same is to avoid things like "Adriatic Sea, Adriatic Sea".

jascottt7 commented 6 years ago

I have the same issue. Your solution is working for me but would be nice to use v-model.