Skip to content

Instantly share code, notes, and snippets.

@SebastienTainon
Last active June 17, 2020 10:07
Show Gist options
  • Save SebastienTainon/7d3add17452f36fda3636835a729bb4e to your computer and use it in GitHub Desktop.
Save SebastienTainon/7d3add17452f36fda3636835a729bb4e to your computer and use it in GitHub Desktop.
Vue-form-generator multiselect field with asynchronous behaviour. You have to return a promise in the search query
<template>
<multiselect
:id="selectOptions.id"
:options="options"
:value="value"
:multiple="selectOptions.multiple"
:track-by="selectOptions.trackBy || null"
:label="selectOptions.label || null"
:searchable="selectOptions.searchable"
:clear-on-select="selectOptions.clearOnSelect"
:hide-selected="selectOptions.hideSelected"
:placeholder="schema.placeholder"
:allow-empty="selectOptions.allowEmpty"
:reset-after="selectOptions.resetAfter"
:close-on-select="selectOptions.closeOnSelect"
:custom-label="customLabel"
:taggable="selectOptions.taggable"
:tag-placeholder="selectOptions.tagPlaceholder"
:max="schema.max || null"
:options-limit="selectOptions.optionsLimit"
:group-values="selectOptions.groupValues"
:group-label="selectOptions.groupLabel"
:block-keys="selectOptions.blockKeys"
:internal-search="selectOptions.internalSearch"
:select-label="selectOptions.selectLabel"
:selected-label="selectOptions.selectedLabel"
:deselect-label="selectOptions.deselectLabel"
:show-labels="selectOptions.showLabels"
:limit="selectOptions.limit"
:limit-text="selectOptions.limitText"
:loading="isLoading"
:disabled="disabled"
:max-height="selectOptions.maxHeight"
:show-pointer="selectOptions.showPointer"
@input="updateSelected"
@select="onSelect"
@remove="onRemove"
@search-change="onSearchChange"
@tag="addTag"
@open="onOpen"
@close="onClose"
:option-height="selectOptions.optionHeight"
:open-direction="selectOptions.openDirection"
>
</multiselect>
</template>
<script>
import {abstractField} from 'vue-form-generator';
export default {
mixins: [abstractField],
data() {
return {
options: [],
isLoading: false,
}
},
computed: {
selectOptions() {
return this.schema.selectOptions || {};
},
customLabel() {
if (typeof this.schema.selectOptions !== "undefined" && typeof this.schema.selectOptions.customLabel !== "undefined" && typeof this.schema.selectOptions.customLabel === "function") {
return this.schema.selectOptions.customLabel;
} else {
//this will let the multiselect library use the default behavior if customLabel is not specified
return undefined;
}
}
},
methods: {
updateSelected(value/*, id*/) {
this.value = value;
},
addTag(newTag, id) {
let onNewTag = this.selectOptions.onNewTag;
if (typeof(onNewTag) === 'function') {
onNewTag(newTag, id, this.options, this.value);
}
},
onSearchChange(searchQuery, id) {
let onSearch = this.selectOptions.onSearch;
if (typeof(onSearch) === 'function' && searchQuery) {
this.isLoading = true;
onSearch(searchQuery, id, this.options).then(response => {
this.options = response;
this.isLoading = false;
});
}
},
onSelect(/*selectedOption, id*/) {
// console.log("onSelect", selectedOption, id);
},
onRemove(/*removedOption, id*/) {
// console.log("onRemove", removedOption, id);
},
onOpen(/*id*/) {
// console.log("onOpen", id);
},
onClose(/*value, id*/) {
// console.log("onClose", value, id);
}
},
created() {
// Check if the component is loaded globally
if (!this.$root.$options.components["multiselect"]) {
console.error("'vue-multiselect' is missing. Please download from https://github.com/monterail/vue-multiselect and register the component globally!");
}
let values = this.schema.values;
if (typeof(values) === 'function') {
this.options = values.apply(this, [this.model, this.schema]);
} else {
this.options = values;
}
}
};
</script>
// This is an example of schema field multiselect with an async GraphQL call
schema () {
let self = this;
return {
fields: [
{
type: "multiselect2",
label: "Partager l'énigme avec :",
model: "sharedUsers",
placeholder: 'Chercher un utilisateur...',
selectOptions: {
multiple: true,
label: 'username',
trackBy: 'id',
searchable: true,
openDirection: 'bottom',
internalSearch: false,
clearOnSelect: false,
closeOnSelect: false,
loading: 'isLoading',
limit: 3,
showNoResults: false,
hideSelected: true,
onSearch: function (searchQuery) {
if (!searchQuery || searchQuery.length === 0) {
return Promise.resolve();
} else {
return self.$apollo.query({
query: getAutocompleteUser,
variables: {
query: searchQuery
}
}).then(data => data.data.autocompleteUser)
}
},
},
values: [],
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment