Enhance Input component: add file input handling and improve label rendering logic
This commit is contained in:
1 parent
0f76978a33
commit
cb0c87a4ca
1 file changed
+41
-3
+41
-3
@@ -10,22 +10,47 @@ interface InputProps {
|
|||||||
name?: string
|
name?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
autocomplete?: AutocompleteType
|
autocomplete?: AutocompleteType
|
||||||
|
label?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = defineModel("value")
|
const value = defineModel<string | File | File[] | null>("value")
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "input", value: string): void
|
(e: "input", value: string): void
|
||||||
|
(e: "file", value: File | File[] | null | undefined): void
|
||||||
(e: "focus"): void
|
(e: "focus"): void
|
||||||
|
(e: "blur"): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const props = defineProps<InputProps>()
|
const props = defineProps<InputProps>()
|
||||||
|
|
||||||
|
const onFileChange = (e: Event) => {
|
||||||
|
const input = e.target as HTMLInputElement
|
||||||
|
const files = input.files
|
||||||
|
|
||||||
|
if (!files || files.length == 0) {
|
||||||
|
value.value = null
|
||||||
|
emit("file", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = files.length == 1 ? files[0] : Array.from(files)
|
||||||
|
|
||||||
|
value.value = result
|
||||||
|
emit("file", result)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper">
|
||||||
<label v-if="$slots.label" :for="props.name">
|
<label v-if="$slots.label || props.label" :for="props.name">
|
||||||
<slot name="label" />
|
<template v-if="!props.label">
|
||||||
|
<slot name="label" />
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ props.label }}
|
||||||
|
</template>
|
||||||
|
|
||||||
<span v-if="props.required" class="required">*</span>
|
<span v-if="props.required" class="required">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
@@ -38,16 +63,29 @@ const props = defineProps<InputProps>()
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
v-if="props.type != 'file'"
|
||||||
:placeholder="props.placeholder"
|
:placeholder="props.placeholder"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
@input="(e) => emit('input', e.target?.value)"
|
@input="(e) => emit('input', e.target?.value)"
|
||||||
@focus="emit('focus')"
|
@focus="emit('focus')"
|
||||||
|
@blur="emit('blur')"
|
||||||
:type="props.type"
|
:type="props.type"
|
||||||
:name="props.name"
|
:name="props.name"
|
||||||
:id="props.name"
|
:id="props.name"
|
||||||
:required="props.required"
|
:required="props.required"
|
||||||
:autocomplete="props.autocomplete"
|
:autocomplete="props.autocomplete"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
@focus="emit('focus')"
|
||||||
|
@blur="emit('blur')"
|
||||||
|
@change="onFileChange"
|
||||||
|
:type="props.type"
|
||||||
|
:name="props.name"
|
||||||
|
:id="props.name"
|
||||||
|
:required="props.required"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in new issue
Block a user