48935e2168
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
92 lines
2.3 KiB
Vue
92 lines
2.3 KiB
Vue
<template>
|
|
<o-field :label-for="id">
|
|
<template #label>
|
|
{{ $t("Add some tags") }}
|
|
<o-tooltip
|
|
variant="dark"
|
|
:label="
|
|
$t('You can add tags by hitting the Enter key or by adding a comma')
|
|
"
|
|
>
|
|
<HelpCircleOutline :size="16" />
|
|
</o-tooltip>
|
|
</template>
|
|
<o-inputitems
|
|
v-model="tagsStrings"
|
|
:data="filteredTags"
|
|
:autocomplete="true"
|
|
:allow-new="true"
|
|
:field="'title'"
|
|
icon="label"
|
|
:maxlength="20"
|
|
:maxitems="10"
|
|
:placeholder="$t('Eg: Stockholm, Dance, Chess…')"
|
|
@typing="debouncedGetFilteredTags"
|
|
:id="id"
|
|
dir="auto"
|
|
>
|
|
</o-inputitems>
|
|
</o-field>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import differenceBy from "lodash/differenceBy";
|
|
import { ITag } from "../../types/tag.model";
|
|
import debounce from "lodash/debounce";
|
|
import { computed, onBeforeMount, ref } from "vue";
|
|
import HelpCircleOutline from "vue-material-design-icons/HelpCircleOutline.vue";
|
|
|
|
const props = defineProps<{
|
|
modelValue: ITag[];
|
|
fetchTags: (text: string) => Promise<ITag[]>;
|
|
}>();
|
|
|
|
const emit = defineEmits(["update:modelValue"]);
|
|
|
|
const text = ref("");
|
|
|
|
const tags = ref<ITag[]>([]);
|
|
|
|
let componentId = 0;
|
|
|
|
onBeforeMount(() => {
|
|
componentId += 1;
|
|
});
|
|
|
|
const id = computed((): string => {
|
|
return `tag-input-${componentId}`;
|
|
});
|
|
|
|
const getFilteredTags = async (newText: string): Promise<void> => {
|
|
text.value = newText;
|
|
tags.value = await props.fetchTags(newText);
|
|
};
|
|
|
|
const debouncedGetFilteredTags = debounce(getFilteredTags, 200);
|
|
|
|
const filteredTags = computed((): ITag[] => {
|
|
return differenceBy(tags.value, props.modelValue, "id").filter(
|
|
(option) =>
|
|
option.title.toString().toLowerCase().indexOf(text.value.toLowerCase()) >=
|
|
0 ||
|
|
option.slug.toString().toLowerCase().indexOf(text.value.toLowerCase()) >=
|
|
0
|
|
);
|
|
});
|
|
|
|
const tagsStrings = computed({
|
|
get(): string[] {
|
|
return props.modelValue.map((tag: ITag) => tag.title);
|
|
},
|
|
set(newTagsStrings: string[]) {
|
|
console.debug("tagsStrings", newTagsStrings);
|
|
const tagEntities = newTagsStrings.map((tag: string | ITag) => {
|
|
if (typeof tag !== "string") {
|
|
return tag;
|
|
}
|
|
return { title: tag, slug: tag } as ITag;
|
|
});
|
|
emit("update:modelValue", tagEntities);
|
|
},
|
|
});
|
|
</script>
|