You need Vue.js version 2.0+ and an Google PLACE API key. This plugin comes without any css, the main goal is to use it with differents framework. To do this, you can pass multiple classes in options and custom the results template (See examples section).
npm install vue-custom-google-autocomplete
yarn add vue-custom-google-autocomplete
import Vue from 'vue'
import CustomGoogleAutocomplete from 'vue-custom-google-autocomplete'
...
Vue.use(CustomGoogleAutocomplete)
Name | Type | Default | Description |
---|---|---|---|
options |
Object | see options section | Plugin options (see options section) |
value |
String | null | Input value (can be use with v-model) |
You can also pass all props available on an input (placeholder, name..)
options = {
apiKey: YOUR_API_KEY,
deepSearch: true,
cors: false,
params: {},
inputClass: '',
inputWrapperClass: '',
mainWrapperClass: '',
focus: false
}
Name | Type | Default | Description |
---|---|---|---|
apiKey |
String | null | Your Google PLACE Api key (REQUIRED) |
deepSearch |
Boolean | true | Get more informations about selected place (geometry etc..) |
cors |
Boolean | false | Set to true when project is running locally |
params |
Object | {} | Google Autocomplete optional parameters |
inputClass . |
String | '' | Input class to match with |
inputWrapperClass |
String | '' | Input Wrapper class. |
mainWrapperClass |
String | '' | Input Wrapper class |
focus |
Boolean | false | Focus input |
debounceTime |
Number | 400 | Time in ms before trigger a new Google api call |
Params object is useful to refine predictions, for example if you want to get first predictions near to a location within a radius distance in a certain language you can set params like this :
params = {
location: `${lat},${lng}`,
radius: 1000,
language: 'fr'
}
See Optional parameters section for more informations
The input part emits three events @blur @focus and @key:value All three send the Input Element reference @key values are :escape :tab :enter :up :down
The results part emits two events @loading and @select @loading is triggered when Google API is requested. @select is triggered when a prediction is selected it send an object with datas about the location
In order to be more flexbile, you are able to make your own results template with slot-scope
This template is accessible via the results
slot
props = {
firstFetch: Boolean,
query: String,
results: Array,
loading: Boolean,
selectPrediction: Function
}
Also two slots are available before and after the input beforeInput
afterInput
<template>
<custom-google-autocomplete
class="dropdown"
:value="query"
:options="options"
:class="{'is-active': dropdownActive }"
@select="selectedPlace = $event"
@focus="dropdownActive = true"
@blur="dropdownActive = false"
>
<template slot="results" slot-scope="props">
<div class="dropdown-menu">
<div class="dropdown-content">
<div class="dropdown-item" style="font-size: 12px;"> Please enter an address </div>
<hr class="dropdown-divider" v-if="props.firstFetch" />
<div class="dropdown-item" v-if="props.loading">
<span> Loading </span>
</div>
<a href="!#" class="dropdown-item"
v-if="props.results.length && !props.loading"
v-for="(prediction, index) in props.results"
:key="index"
@click.prevent="props.selectPrediction(prediction)"
>
<span> {{ prediction.description }} </span>
</a>
</div>
</div>
</template>
</custom-google-autocomplete>
</template>
<script>
export default {
data() {
return {
selectedPlace: null,
dropdownActive: false,
query: '',
options: {
apiKey: process.env.VUE_APP_PLACE_API_KEY,
deepSearch: true,
cors: true,
focus: false,
inputClass: 'input',
inputWrapperClass: 'dropdown-trigger',
params: {
location: '43.3,5.4',
radius: 1000,
language: 'fr'
}
}
}
}
}
</script>
<template>
<custom-google-autocomplete
class="dropdown"
:value="query"
placeholder="Please, enter an address"
:options="options"
:class="{'show': dropdownActive }"
@select="selectedPlace = $event"
@focus="dropdownActive = true"
@blur="dropdownActive = false"
>
<template slot="results" slot-scope="props">
<div class="dropdown-menu" :class="{'show': dropdownActive && props.query }">
<div class="dropdown-item-text" v-if="hasNoResults(props)">
<span style="font-size: 12px; color: #919191">
No results found for <strong>"{{props.query}}"</strong>
</span>
</div>
<div class="dropdown-item-text" v-if="hasResults(props)">
<span style="font-size: 12px; color: #919191">
{{ props.results.length }} results found for <strong>"{{props.query}}"</strong>
</span>
</div>
<div class="dropdown-item-text" v-if="props.loading">
<span style="font-size: 12px; color: #919191">
Loading...
</span>
</div>
<div class="dropdown-divider" v-if="props.query && !hasNoResults(props) && !props.loading"></div>
<a href="!#" class="dropdown-item"
v-if="props.results.length && !props.loading"
v-for="(prediction, index) in props.results"
:key="index"
style="font-size: 13px;"
@click.prevent="props.selectPrediction(prediction)"
>
<span> {{ prediction.description }} </span>
</a>
</div>
</template>
</custom-google-autocomplete>
</template>
<script>
export default {
data() {
return {
selectedPlace: null,
dropdownActive: false,
query: '',
options: any = {
apiKey: process.env.VUE_APP_PLACE_API_KEY,
deepSearch: true,
cors: true,
focus: false,
inputClass: 'form-control',
inputWrapperClass: '',
params: {
location: '45.52345,-122.67621',
radius: 1000,
language: 'en'
}
}
}
},
methods: {
hasNoResults(props) {
return !props.results.length && !props.loading && props.firstFetch && props.query
},
hasResults(props) {
return props.results.length > 0 && !props.loading && props.firstFetch && props.query
}
}
}
</script>