|
| 1 | +<!-- eslint-disable vue/multi-word-component-names --> |
1 | 2 | <template v-once> |
2 | 3 | <textarea |
3 | 4 | v-if="type === 'textarea'" |
|
9 | 10 | /> |
10 | 11 | </template> |
11 | 12 |
|
12 | | -<script lang="ts"> |
| 13 | +<script setup lang="ts"> |
13 | 14 | import Tagify from '@yaireo/tagify' |
14 | 15 | import '@yaireo/tagify/dist/tagify.css' |
15 | | -import type { PropType } from 'vue' |
16 | | -export default defineComponent({ |
17 | | - name: 'TagsInput', |
18 | | - props: { |
19 | | - type: { |
20 | | - type: String, |
21 | | - default: 'input', |
22 | | - }, |
23 | | - settings: { |
24 | | - type: Object as PropType<Tagify.TagifySettings>, |
25 | | - default: () => ({}), |
26 | | - }, |
27 | | - value: { |
28 | | - type: Array as PropType<Tagify.TagData[]>, // e.g. [{"value":"cat"}, {"value":"dog"}]' |
29 | | - default: () => [], |
30 | | - }, |
31 | | - delimiters: { |
32 | | - type: String, |
33 | | - default: ',', |
34 | | - }, |
35 | | - whitelist: { |
36 | | - type: Array as PropType<Tagify.TagData[]>, |
37 | | - default: () => [], |
38 | | - }, |
39 | | - tagClass: { |
40 | | - type: String, |
41 | | - default: '', |
42 | | - }, |
| 16 | +
|
| 17 | +const props = withDefaults( |
| 18 | + defineProps<{ |
| 19 | + type?: string |
| 20 | + settings?: Tagify.TagifySettings |
| 21 | + value?: Tagify.TagData[] |
| 22 | + delimiters?: string |
| 23 | + whitelist?: Tagify.TagData[] |
| 24 | + tagClass?: string |
| 25 | + }>(), |
| 26 | + { |
| 27 | + type: 'input', |
| 28 | + settings: () => ({}), |
| 29 | + value: () => [], |
| 30 | + delimiters: ',', |
| 31 | + whitelist: () => [], |
| 32 | + tagClass: '', |
43 | 33 | }, |
44 | | - data() { |
45 | | - return { |
46 | | - tagify: null as Tagify | null, |
| 34 | +) |
| 35 | +
|
| 36 | +const emit = defineEmits<{ |
| 37 | + input: [value: string | Tagify.TagData[]] |
| 38 | +}>() |
| 39 | +
|
| 40 | +const tagify = ref<Tagify | null>(null) |
| 41 | +
|
| 42 | +watch( |
| 43 | + () => props.value, |
| 44 | + (newVal) => { |
| 45 | + // Value modified externally, update tagify |
| 46 | + if (newVal) { |
| 47 | + // @ts-expect-error: problem in tagify types |
| 48 | + tagify.value?.loadOriginalValues(newVal) |
47 | 49 | } |
48 | 50 | }, |
49 | | - watch: { |
50 | | - value(newVal, _oldVal) { |
51 | | - // Value modified externally, update tagify |
52 | | - this.tagify?.loadOriginalValues(newVal) |
53 | | - }, |
54 | | - }, |
55 | | - mounted() { |
56 | | - // Install tagify |
57 | | - const tagifySettings: Tagify.TagifySettings = { |
58 | | - delimiters: this.delimiters, |
59 | | - whitelist: this.whitelist, |
60 | | - ...this.settings, |
61 | | - } |
62 | | - if (this.tagClass) { |
63 | | - if (tagifySettings.classNames) { |
64 | | - tagifySettings.classNames.tag = 'tagify__tag ' + this.tagClass |
65 | | - } else { |
66 | | - tagifySettings.classNames = { |
67 | | - tag: 'tagify__tag ' + this.tagClass, |
68 | | - } |
| 51 | +) |
| 52 | +
|
| 53 | +onMounted(() => { |
| 54 | + // Install tagify |
| 55 | + const tagifySettings: Tagify.TagifySettings = { |
| 56 | + delimiters: props.delimiters, |
| 57 | + whitelist: props.whitelist, |
| 58 | + ...props.settings, |
| 59 | + } |
| 60 | + if (props.tagClass) { |
| 61 | + if (tagifySettings.classNames) { |
| 62 | + tagifySettings.classNames.tag = 'tagify__tag ' + props.tagClass |
| 63 | + } else { |
| 64 | + tagifySettings.classNames = { |
| 65 | + tag: 'tagify__tag ' + props.tagClass, |
69 | 66 | } |
70 | 67 | } |
| 68 | + } |
71 | 69 |
|
72 | | - this.tagify = new Tagify( |
73 | | - this.$el as HTMLTextAreaElement | HTMLInputElement, |
74 | | - tagifySettings, |
75 | | - ) |
76 | | - }, |
77 | | - unmounted() { |
78 | | - this.tagify?.destroy() |
79 | | - }, |
80 | | - methods: { |
81 | | - onChange(event: { target: EventTarget | null }) { |
82 | | - // Update value prop |
83 | | - this.$emit( |
84 | | - 'input', |
85 | | - (event.target as HTMLInputElement | null)?.value ?? [], |
86 | | - ) |
87 | | - }, |
88 | | - }, |
| 70 | + // Get the actual DOM element (textarea or input) from the component root |
| 71 | + const instance = getCurrentInstance() |
| 72 | + const element = instance?.proxy?.$el as HTMLTextAreaElement | HTMLInputElement |
| 73 | + if (element) { |
| 74 | + tagify.value = new Tagify(element, tagifySettings) |
| 75 | + } |
89 | 76 | }) |
| 77 | +
|
| 78 | +onUnmounted(() => { |
| 79 | + tagify.value?.destroy() |
| 80 | +}) |
| 81 | +
|
| 82 | +function onChange(event: { target: EventTarget | null }) { |
| 83 | + // Update value prop |
| 84 | + emit('input', (event.target as HTMLInputElement | null)?.value ?? []) |
| 85 | +} |
90 | 86 | </script> |
91 | 87 |
|
92 | 88 | <style> |
|
0 commit comments