Last active
June 17, 2020 10:07
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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