Skip to content
This repository has been archived by the owner on Mar 9, 2024. It is now read-only.

add support for multiple prop #328

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 65 additions & 13 deletions docs/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
Algolia Places
<v-icon right>open_in_new</v-icon>
</v-btn>
<v-btn text href="https://vuetifyjs.com/components/autocompletes" target="_blank">
Vuetify Autocomplete
<v-icon right>open_in_new</v-icon>
</v-btn>
</v-toolbar-items>
</v-app-bar>
<v-content>
Expand All @@ -20,7 +24,9 @@
<v-col md="10" lg="8" xl="6">
<h2 class="display-2 text-center">Vuetify Algolia Places</h2>
<vuetify-algolia-places
v-model="place"
v-model="placeFormatted"
:search-input.sync="query"
:cache-items="options.multiple"
v-bind="options"
class="mt-10 mb-4"
@error="onError"
Expand Down Expand Up @@ -70,6 +76,15 @@
<v-switch v-model="options.singleLine" label="Single line" color="primary" hide-details />
<v-switch v-model="options.filled" label="Style filled" color="primary" hide-details />
<v-switch v-model="options.solo" label="Style solo" color="primary" hide-details />
<v-switch
v-model="options.multiple"
label="Multiple"
color="primary"
hide-details
@change="updateModel"
/>
<v-switch v-model="options.chips" label="Chips" color="primary" hide-details />
<v-switch v-model="options.deletableChips" label="Deletable chips" color="primary" hide-details />
</v-col>
<v-col cols="12" md8 sm="12">
<v-text-field v-model="options.label" label="Label" />
Expand All @@ -92,10 +107,10 @@
<code class="pa-3 mb-3 d-block">{{ usageCode }}</code>
</v-col>
</v-row>
<v-row v-if="place">
<v-row v-if="showModel">
<v-col>
<h2 class="headline mb-3">Place</h2>
<code class="mb-3 pa-3 d-block">{{ JSON.stringify(place, null, 2) }}</code>
<h2 class="headline mb-3">Model</h2>
<code class="mb-3 pa-3 d-block">{{ JSON.stringify(placeFormatted, null, 2) }}</code>
</v-col>
</v-row>
</v-col>
Expand All @@ -106,13 +121,12 @@
</template>

<script>
const initialPlace = '30 Rue du Sergent Michel Berthet, Lyon';

export default {
name: 'App',
data() {
return {
place: initialPlace,
query: '30 Rue du Sergent Michel Berthet, Lyon',
place: null,
types: ['city', 'country', 'address', 'busStop', 'trainStation', 'townhall', 'airport'],
languages: ['fr', 'en', 'es'],
countries: ['fr', 'gb', 'es'],
Expand All @@ -133,10 +147,16 @@ export default {
solo: true,
label: 'Search a place',
appendIcon: 'location_on',
multiple: false,
chips: false,
deletableChips: false,
},
};
},
computed: {
showModel() {
return Array.isArray(this.place) ? this.place.length > 0 : this.place;
},
installationCode() {
return `import Vue from 'vue';
import VuetifyAlgoliaPlaces from 'vuetify-algolia-places';
Expand Down Expand Up @@ -205,17 +225,42 @@ Vue.use(VuetifyAlgoliaPlaces, {
code += `\n solo`;
}

if (this.options.multiple) {
code += `\n multiple`;
}

if (this.options.chips) {
code += `\n chips`;
}

if (this.options.deletableChips) {
code += `\n deletableChips`;
}

code += '\n/>';
return code;
},
placeFormatted: {
get() {
if (Array.isArray(this.place)) {
// Remove hit and rawAnswer props from every object in place array
return this.place.map(({ hit, rawAnswer, ...p }) => p);
}

if (this.place) {
delete this.place.hit;
delete this.place.rawAnswer;
return this.place;
}

return this.place;
},
set(value) {
this.place = value;
},
},
},
watch: {
place() {
if (this.place) {
delete this.place.hit;
delete this.place.rawAnswer;
}
},
'options.filled': function(filled) {
if (filled) {
this.options.solo = false;
Expand All @@ -234,6 +279,13 @@ Vue.use(VuetifyAlgoliaPlaces, {
onClear() {
console.log('Clear');
},
updateModel(multiple) {
if (multiple) {
this.place = [];
} else {
this.place = null;
}
},
},
};
</script>
51 changes: 23 additions & 28 deletions src/VuetifyAlgoliaPlaces.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<template>
<v-autocomplete
v-model="place"
:value="value"
v-bind="$attrs"
:items="places"
:loading="loading"
:search-input.sync="query"
:filter="filter"
return-object
item-text="value"
:append-icon="appendIcon"
v-on="$listeners"
@input="onInput"
@input="$emit('input', $event)"
@click:clear="onClear"
@change="query = ''"
>
<template slot="item" slot-scope="data">
<template v-if="typeof data.item !== 'object'">
Expand All @@ -38,11 +38,12 @@ export default {
name: 'VuetifyAlgoliaPlaces',
props: {
value: {
type: [Object, String],
required: false,
default() {
return {};
},
type: [Object, Array],
default: () => ({}),
},
searchInput: {
type: String,
default: '',
},
type: {
type: String,
Expand Down Expand Up @@ -105,22 +106,20 @@ export default {
},
},
data() {
// The initial value can be a string or an object
// eslint-disable-next-line no-nested-ternary
const initialValue = this.value ? (typeof this.value === 'string' ? this.value : this.value.value) : null;
const initialPlace = { value: initialValue };

return {
loading: false,
query: initialValue,
place: initialPlace,
places: initialValue ? [initialPlace] : [],
filter() {
return true; // display all items, Algolia Places is already doing the work
},
places: [],
};
},
computed: {
query: {
get() {
return this.searchInput;
},
set(value) {
this.$emit('update:search-input', value);
},
},
searchOptions() {
const searchOptions = { query: this.query };

Expand Down Expand Up @@ -176,8 +175,7 @@ export default {
handler(newVal, oldVal) {
if (newVal.query !== null && newVal.query === oldVal.query) {
this.debouncedSearchPlaces(place => {
this.place = place;
this.onInput();
this.$emit('input', place);
});
}
},
Expand All @@ -188,8 +186,7 @@ export default {

if (this.query !== null) {
this.searchPlaces(place => {
this.place = place;
this.onInput();
this.$emit('input', place);
});
}
},
Expand All @@ -204,7 +201,6 @@ export default {
this.placesClient
.search(this.searchOptions)
.then(content => {
this.loading = false;
this.places = content.hits
.map((hit, hitIndex) =>
formatHit({
Expand All @@ -225,16 +221,15 @@ export default {
}
})
.catch(error => {
this.loading = false;
this.$emit('error', error);
})
.finally(() => {
this.loading = false;
});
},
debouncedSearchPlaces(callback = () => {}) {
return this.searchPlaces(callback);
},
onInput() {
this.$emit('input', this.place);
},
onClear() {
this.$emit('input', null);
this.$emit('clear');
Expand Down