uses v-model remove tags by clicking x add new tags by typing and pressing space, comma, period
Last active
January 28, 2024 02:08
-
-
Save JavascriptMick/0a5113e90b069d3af5637de16070ea89 to your computer and use it in GitHub Desktop.
Simple Tag List Component in Vue 3 and Tailwind
This file contains hidden or 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> | |
<div | |
class="flex flex-wrap items-center border border-gray-300 rounded p-2" | |
id="tag-container"> | |
<div | |
v-for="(tag, index) in modelValue" | |
:key="index" | |
class="flex items-center bg-gray-200 rounded px-3 py-1"> | |
<span>{{ tag }}</span> | |
<button | |
class="ml-2 text-gray-600 hover:text-gray-800" | |
@click.prevent="removeItem(index)"> | |
× | |
</button> | |
</div> | |
<input | |
type="text" | |
id="tag-input" | |
class="flex-1 border-none focus:ring-0" | |
@keypress.enter.prevent="doNothing" | |
@keyup.prevent="handleKeyPress" | |
placeholder="type a keyword and hit [space]" /> | |
</div> | |
</template> | |
<script> | |
import { defineComponent, toRefs } from 'vue'; | |
export default defineComponent({ | |
name: 'TagList', | |
props: { | |
modelValue: Array | |
}, | |
setup(props, { emit }) { | |
const { modelValue } = toRefs(props); | |
const doNothing = async event => {}; // null handler for enter to prevent odd invocation of removeItem when you press enter in the input box | |
const removeItem = index => { | |
const clonedValue = [...modelValue.value]; | |
clonedValue.splice(index, 1); | |
emit('update:modelValue', clonedValue); | |
}; | |
const handleKeyPress = async event => { | |
if (event.key === ' ' || event.key === ',' || event.key === '.') { | |
const trimmedValue = event.target.value.replace(/[,\s.]/g, ''); | |
if ( | |
trimmedValue && | |
trimmedValue.length > 0 && | |
!modelValue.value.includes(trimmedValue) | |
) { | |
console.log(`trimmedValue: ${trimmedValue}`); | |
const clonedValue = [...modelValue.value, trimmedValue]; | |
await emit('update:modelValue', clonedValue); | |
} | |
event.target.value = ''; | |
} | |
}; | |
return { | |
modelValue, | |
removeItem, | |
handleKeyPress, | |
doNothing | |
}; | |
} | |
}); | |
</script> |
This file contains hidden or 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> | |
<TagList | |
id="my-tags" | |
v-model="tags" | |
class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"></TagList> | |
</template> | |
<script setup> | |
import { ref } from 'vue'; | |
const tags = ref(['aaa']); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment