如何使用标签输入组件将现有 Vue 3 表单中的文本输入更改为标签?
How to change text inputs into tags, in an existing Vue 3 form, using a Tag Input Component?
我在 Vue 3 项目中有一个已成功发布到 Cloud Firestore 数据库的现有表单。
如何使用标签输入组件like this? Here's a link to it on CodeSandbox[将 type="text"
输入字段的 two 更改为标签输入=13=]
独立教程非常清晰,效果很好。我正在努力解决的问题是如何将其合并到现有的 Vue 3 表单中并继续将所有内容发布到 Firestore 数据库中。
我从下面的“基本”代码中剥离了样式和许多其他输入字段:
<template>
<form @submit.prevent="handleSubmit" >
<h3>What kind of pet?</h3>
<div class="space-y-0">
<select required name="pet_type" id="pet_type" v-model="pet_type">
<option value="">Please select</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="wolverine">Wolverine</option>
</select>
</div>
<hr>
<div> <!-- Want to change this into the first tag input -->
<h3>Pros</h3>
<div for="petPros">What are 3 positive things about this pet?</div>
<input type="text" placeholder="separate , with , commas" id="petPros" v-model="petPros">
<label for="petPros">separate , with , commas</label>
</div>
<hr>
<div>
<h3>Cons</h3> <!-- Want to change this into a second tag input -->
<div for="petCons">And what are 3 negative things about this pet?</div>
<input type="text" placeholder="separate , with , commas" id="petPros" v-model="petCons">
<label for="petCons">separate , with , commas</label>
</div>
<hr>
<h3>Privacy</h3>
<div>
<div>
<input type="radio" id="Fullpublic" value="Fullpublic" name="reviewPrivacy" required v-model="reviewPrivacy">
<label class="text-base inline-flex ml-4 align-bottom" for="Fullpublic">Public</label>
</div>
<div>
<input type="radio" id="keepFullyPrivate" value="keepFullyPrivate" name="reviewPrivacy" required v-model="reviewPrivacy">
<label class="text-base inline-flex ml-4 align-bottom" for="keepFullyPrivate">Private</label>
</div>
</div>
<hr>
<button v-if="!isPending" >Submit</button>
<button v-else disabled>Saving...</button>
</form>
</template>
<script>
import { ref } from 'vue'
import useStorage from '@/composables/useStorage'
import useCollection from '@/composables/useCollection'
export default {
setup() {
const { filePath, url, uploadImage } = useStorage()
const { error, addDoc } = useCollection('reviews')
const { user } = getUser()
const router = useRouter()
const pet_type = ref('')
const petPros = ref('')
const petCons = ref('')
const reviewPrivacy = ref('')
const file = ref(null)
const fileError = ref(null)
const isPending = ref(false)
const handleSubmit = async () => {
if (file.value) {
isPending.value = true
await uploadImage(file.value)
const res = await addDoc({
pet_type: pet_type.value,
petPros: petPros.value,
petCons: petCons.value,
reviewPrivacy: reviewPrivacy.value,
userId: user.value.uid,
userName: user.value.displayName,
createdAt: timestamp()
})
isPending.value = false
if (!error.value) {
router.push({ name: 'ReviewDetails', params: { id: res.id }})
}
}
}
// allowed file types
const types = ['image/png', 'image/jpeg']
const handleChange = (e) => {
let selected = e.target.files[0]
console.log(selected)
if (selected && types.includes(selected.type)) {
file.value = selected
fileError.value = null
} else {
file.value = null
fileError.value = 'Please select an image file (png, jpg or jpeg)'
}
}
return { pet_type, petPros, petCons, reviewPrivacy, handleSubmit, fileError, handleChange, isPending }
}
}
</script>
<style>
</style>
感谢您的帮助!
表格中,将两个<input type="text">
替换为<TagInput>
。保持 v-model
不变,因为 TabInput
实现 v-model
.
<!-- BEFORE -->
<input type="text" placeholder="separate , with , commas" id="petPros" v-model="petPros">
<input type="text" placeholder="separate , with , commas" id="petPros" v-model="petCons">
<!-- AFTER -->
<TagInput id="petPros" v-model="petPros" />
<TagInput id="petCons" v-model="petCons" />
在表单组件中本地注册TagInput.vue
:
import TagInput from "./TagInput.vue";
export default {
components: {
TagInput,
},
}
将petPros
和petCons
ref
的初始值改为数组,因为TabInput
输出的是输入标签的字符串数组值:
// BEFORE
const petPros = ref('')
const petCons = ref('')
// AFTER
const petPros = ref([])
const petCons = ref([])
TabInput
通常会在点击 TAB 时添加一个标签,但您的占位符建议您使用逗号键 , 代替。为此,请更新 @keydown
绑定中的修饰符:
<!-- BEFORE -->
<input v-model="newTag"
@keydown.prevent.tab="addTag(newTag)"
>
<!-- AFTER -->
<input v-model="newTag"
@keydown.prevent.,="addTag(newTag)"
>
我在 Vue 3 项目中有一个已成功发布到 Cloud Firestore 数据库的现有表单。
如何使用标签输入组件like this? Here's a link to it on CodeSandbox[将 type="text"
输入字段的 two 更改为标签输入=13=]
独立教程非常清晰,效果很好。我正在努力解决的问题是如何将其合并到现有的 Vue 3 表单中并继续将所有内容发布到 Firestore 数据库中。
我从下面的“基本”代码中剥离了样式和许多其他输入字段:
<template>
<form @submit.prevent="handleSubmit" >
<h3>What kind of pet?</h3>
<div class="space-y-0">
<select required name="pet_type" id="pet_type" v-model="pet_type">
<option value="">Please select</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="wolverine">Wolverine</option>
</select>
</div>
<hr>
<div> <!-- Want to change this into the first tag input -->
<h3>Pros</h3>
<div for="petPros">What are 3 positive things about this pet?</div>
<input type="text" placeholder="separate , with , commas" id="petPros" v-model="petPros">
<label for="petPros">separate , with , commas</label>
</div>
<hr>
<div>
<h3>Cons</h3> <!-- Want to change this into a second tag input -->
<div for="petCons">And what are 3 negative things about this pet?</div>
<input type="text" placeholder="separate , with , commas" id="petPros" v-model="petCons">
<label for="petCons">separate , with , commas</label>
</div>
<hr>
<h3>Privacy</h3>
<div>
<div>
<input type="radio" id="Fullpublic" value="Fullpublic" name="reviewPrivacy" required v-model="reviewPrivacy">
<label class="text-base inline-flex ml-4 align-bottom" for="Fullpublic">Public</label>
</div>
<div>
<input type="radio" id="keepFullyPrivate" value="keepFullyPrivate" name="reviewPrivacy" required v-model="reviewPrivacy">
<label class="text-base inline-flex ml-4 align-bottom" for="keepFullyPrivate">Private</label>
</div>
</div>
<hr>
<button v-if="!isPending" >Submit</button>
<button v-else disabled>Saving...</button>
</form>
</template>
<script>
import { ref } from 'vue'
import useStorage from '@/composables/useStorage'
import useCollection from '@/composables/useCollection'
export default {
setup() {
const { filePath, url, uploadImage } = useStorage()
const { error, addDoc } = useCollection('reviews')
const { user } = getUser()
const router = useRouter()
const pet_type = ref('')
const petPros = ref('')
const petCons = ref('')
const reviewPrivacy = ref('')
const file = ref(null)
const fileError = ref(null)
const isPending = ref(false)
const handleSubmit = async () => {
if (file.value) {
isPending.value = true
await uploadImage(file.value)
const res = await addDoc({
pet_type: pet_type.value,
petPros: petPros.value,
petCons: petCons.value,
reviewPrivacy: reviewPrivacy.value,
userId: user.value.uid,
userName: user.value.displayName,
createdAt: timestamp()
})
isPending.value = false
if (!error.value) {
router.push({ name: 'ReviewDetails', params: { id: res.id }})
}
}
}
// allowed file types
const types = ['image/png', 'image/jpeg']
const handleChange = (e) => {
let selected = e.target.files[0]
console.log(selected)
if (selected && types.includes(selected.type)) {
file.value = selected
fileError.value = null
} else {
file.value = null
fileError.value = 'Please select an image file (png, jpg or jpeg)'
}
}
return { pet_type, petPros, petCons, reviewPrivacy, handleSubmit, fileError, handleChange, isPending }
}
}
</script>
<style>
</style>
感谢您的帮助!
表格中,将两个
<input type="text">
替换为<TagInput>
。保持v-model
不变,因为TabInput
实现v-model
.<!-- BEFORE --> <input type="text" placeholder="separate , with , commas" id="petPros" v-model="petPros"> <input type="text" placeholder="separate , with , commas" id="petPros" v-model="petCons"> <!-- AFTER --> <TagInput id="petPros" v-model="petPros" /> <TagInput id="petCons" v-model="petCons" />
在表单组件中本地注册
TagInput.vue
:import TagInput from "./TagInput.vue"; export default { components: { TagInput, }, }
将
petPros
和petCons
ref
的初始值改为数组,因为TabInput
输出的是输入标签的字符串数组值:// BEFORE const petPros = ref('') const petCons = ref('') // AFTER const petPros = ref([]) const petCons = ref([])
TabInput
通常会在点击 TAB 时添加一个标签,但您的占位符建议您使用逗号键 , 代替。为此,请更新@keydown
绑定中的修饰符:<!-- BEFORE --> <input v-model="newTag" @keydown.prevent.tab="addTag(newTag)" > <!-- AFTER --> <input v-model="newTag" @keydown.prevent.,="addTag(newTag)" >