Skip to content

Instantly share code, notes, and snippets.

@sryabov
Created June 20, 2018 20:07
Show Gist options
  • Select an option

  • Save sryabov/43b65d4628543c5a5143d4a0e2220835 to your computer and use it in GitHub Desktop.

Select an option

Save sryabov/43b65d4628543c5a5143d4a0e2220835 to your computer and use it in GitHub Desktop.

Revisions

  1. sryabov created this gist Jun 20, 2018.
    152 changes: 152 additions & 0 deletions autocomplete.vue
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,152 @@
    <template>
    <v-autocomplete
    v-model="select"
    :loading="loading"
    :items="items"
    :search-input.sync="search"
    no-filter
    hide-selected
    clearable
    return-object
    :label="label"
    :name="name"
    :required="required"
    :rules="[v => !this.required || !!v || 'Необходимо выбрать']"
    :error="error"
    :error-message="errorMessage"
    />
    </template>
    <script>
    import _ from 'lodash';
    import Axios from 'axios';
    import API_HELICOPTERS from '@/api/helicopters';

    export default {
    props: {
    value: String,
    preload: {
    type: Array,
    default: () => [],
    },
    error: Object,
    errorMessage: Object,
    required: {
    type: Boolean,
    default: false,
    },
    label: {
    type: String,
    default: 'Вертолет',
    },
    name: String,
    },
    data() {
    return {
    select: null,
    search: null,
    items: [],
    loading: false,
    apiSource: null,
    };
    },
    created() {
    this.preloading();
    },
    watch: {
    select(value) {
    this.$emit('input', value ? value.value : null);
    },
    value(value) {
    this.setValue(value);
    },
    search(query) {
    if (query && (!this.select || this.select.text !== query)) {
    this.querySearch(query);
    }
    },
    },
    methods: {
    setValue(id) {
    if (!id) {
    this.select = null;
    } else if (!this.select || this.select.value !== id) {
    const item = this.getItemById(id);
    if (item) {
    this.select = item;
    } else {
    this.preloading();
    }
    }
    },
    getItemById(id) {
    return this.items.find(item => item.value === id);
    },
    querySearch: _.debounce(
    function querySearch(query) {
    this.loading = true;

    (this.apiQuery({ value: query }))
    .then((response) => {
    this.items = _.unionBy(this.items, response, '@id');
    })
    .finally(() => {
    this.loading = false;
    })
    ;
    },
    500,
    ),
    preloading() {
    const preload = this.preload.slice();

    if (this.value) {
    preload.push(this.value);
    }

    if (preload.length > 0) {
    this.loading = true;

    (this.apiQuery({ ids: preload }))
    .then((response) => {
    this.items = response;
    if (this.value) {
    const item = this.getItemById(this.value);
    if (!item) {
    const item404 = {
    value: this.value,
    text: `[${this.value}]`,
    };
    this.items.push(item404);
    this.select = item404;
    } else {
    this.select = item;
    }
    }
    })
    .finally(() => {
    this.loading = false;
    })
    ;
    }
    },
    apiQuery(filters) {
    if (this.apiSource) {
    this.apiSource.cancel();
    }
    this.apiSource = Axios.CancelToken.source();

    return API_HELICOPTERS.list(
    {
    filters: { id: filters.ids, boardNumber: filters.value },
    properties: ['type', 'boardNumber', 'seats', 'maxDistance', 'maxFlightTime'],
    },
    { cancelToken: this.apiSource.token },
    ).then(data => data.items.map(item => ({
    ...item,
    value: item['@id'],
    text: item.boardNumber,
    })));
    },
    },
    };
    </script>