feat: allow selecting multiple labels at once (#945)

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#945
Reviewed-by: dpschen <dpschen@noreply.kolaente.de>
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
This commit is contained in:
konrad 2021-11-09 19:07:06 +00:00
parent 70a50ca1c2
commit 9b7882de7a
2 changed files with 20 additions and 16 deletions

View File

@ -7,7 +7,9 @@
@focus="focus" @focus="focus"
> >
<div class="control" :class="{'is-loading': loading || localLoading}"> <div class="control" :class="{'is-loading': loading || localLoading}">
<div class="input-wrapper input" :class="{'has-multiple': multiple && Array.isArray(internalValue) && internalValue.length > 0}"> <div
class="input-wrapper input"
:class="{'has-multiple': hasMultiple}">
<template v-if="Array.isArray(internalValue)"> <template v-if="Array.isArray(internalValue)">
<template v-for="(item, key) in internalValue"> <template v-for="(item, key) in internalValue">
<slot name="tag" :item="item"> <slot name="tag" :item="item">
@ -81,7 +83,7 @@
</template> </template>
<script> <script>
import { i18n } from '@/i18n' import {i18n} from '@/i18n'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside' import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
export default { export default {
@ -134,9 +136,7 @@ export default {
// If true, will provide an "add this as a new value" entry which fires an @create event when clicking on it. // If true, will provide an "add this as a new value" entry which fires an @create event when clicking on it.
creatable: { creatable: {
type: Boolean, type: Boolean,
default() { default: false,
return false
},
}, },
// The text shown next to the new value option. // The text shown next to the new value option.
createPlaceholder: { createPlaceholder: {
@ -155,23 +155,17 @@ export default {
// If true, allows for selecting multiple items. v-model will be an array with all selected values in that case. // If true, allows for selecting multiple items. v-model will be an array with all selected values in that case.
multiple: { multiple: {
type: Boolean, type: Boolean,
default() { default: false,
return false
},
}, },
// If true, displays the search results inline instead of using a dropdown. // If true, displays the search results inline instead of using a dropdown.
inline: { inline: {
type: Boolean, type: Boolean,
default() { default: false,
return false
},
}, },
// If true, shows search results when no query is specified. // If true, shows search results when no query is specified.
showEmpty: { showEmpty: {
type: Boolean, type: Boolean,
default() { default: true,
return true
},
}, },
// The delay in ms after which the search event will be fired. Used to avoid hitting the network on every keystroke. // The delay in ms after which the search event will be fired. Used to avoid hitting the network on every keystroke.
searchDelay: { searchDelay: {
@ -180,8 +174,12 @@ export default {
return 200 return 200
}, },
}, },
closeAfterSelect: {
type: Boolean,
default: true,
},
}, },
/** /**
* Available events: * Available events:
* @search: Triggered every time the search query input changes * @search: Triggered every time the search query input changes
@ -234,6 +232,9 @@ export default {
return this.searchResults return this.searchResults
}, },
hasMultiple() {
return this.multiple && Array.isArray(this.internalValue) && this.internalValue.length > 0
},
}, },
methods: { methods: {
// Searching will be triggered with a 200ms delay to avoid searching on every keyup event. // Searching will be triggered with a 200ms delay to avoid searching on every keyup event.
@ -285,7 +286,9 @@ export default {
this.$emit('update:modelValue', this.internalValue) this.$emit('update:modelValue', this.internalValue)
this.$emit('select', object) this.$emit('select', object)
this.setSelectedObject(object) this.setSelectedObject(object)
this.closeSearchResults() if (this.closeAfterSelect && this.filteredSearchResults.length > 0 && !this.creatableAvailable) {
this.closeSearchResults()
}
}, },
setSelectedObject(object, resetOnly = false) { setSelectedObject(object, resetOnly = false) {
this.internalValue = object this.internalValue = object

View File

@ -12,6 +12,7 @@
:create-placeholder="$t('task.label.createPlaceholder')" :create-placeholder="$t('task.label.createPlaceholder')"
v-model="labels" v-model="labels"
:search-delay="10" :search-delay="10"
:close-after-select="false"
> >
<template #tag="props"> <template #tag="props">
<span <span