Search code examples
javascriptvue.jsvue-componentvuexalgolia

Algolia vue-places: Clear input after selection


I'm using the vue-places component to render an Algolia places search input in Vue - it works brilliantly.

After a user selects / accepts a suggestion from the search dropdown, I want to clear the input and allow them to search again. Based on the standard example provided, I have tried to set form.country.label v-model value back to null in the change handler:

<template>
  <places
    v-model="form.country.label"
    placeholder="Where are we going ?"
    @change="selectLocation"
    :options="options">
  </places>
</template>

<script>
import Places from 'vue-places';

export default {
  data() {
    return {
      options: {
        appId: <YOUR_PLACES_APP_ID>,
        apiKey: <YOUR_PLACES_API_KEY>,
        countries: ['US'],
      },
      form: {
        country: {
          label: null,
          data: {},
        },
      },
    };
  },
  components: {
    Places,
  },
    methods: {
      selectLocation: function(event: any) {
        if (event.name !== undefined) {
          /**
           * implementation not important
           */

          this.form.country.label = null;
        }
      }
    }
}
</script>

The selectLocation method fires as expected - but I cannot find any way to rest the input value to be empty.

How can I update a data value from a component method and have this reflected in a referencing component - in this case the Algolia places input?


Solution

  • The issue occurs because of how vue-places is proxying change events from the underlying implementation. When a change event is received, it broadcasts the same event and then updates the input value:

    Places.vue:

    this.placesAutocomplete.on('change', (e) => {
      this.$emit('change', e.suggestion);
      this.updateValue(e.suggestion.value);
    });
    

    This means that any attempt to set a value in our change handler will immediately be overridden.

    My solution is to create a ref to the vue-places instance and then use the built-in Vue.nextTick to use the internal places.js setVal method after the call to updateValue:

        methods: {
          selectLocation: function(event: any) {
            if (event.name !== undefined) {
              // do something with the value
    
              Vue.nextTick(() => {
                // clear the input value on the next update
                this.$refs.placesSearch.placesAutocomplete.setVal(null);
              });
            }
          }
        }