mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-20 06:51:46 +01:00
fix(Input/Textarea): add v-model modifiers (#856)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
v-bind="attrs"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
@change="onChange"
|
||||
>
|
||||
<slot />
|
||||
|
||||
@@ -36,9 +37,10 @@ import { ref, computed, toRef, onMounted, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { defu } from 'defu'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, looseToNumber } from '../../utils'
|
||||
import type { NestedKeyOf, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
@@ -156,6 +158,10 @@ export default defineComponent({
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
},
|
||||
modelModifiers: {
|
||||
type: Object as PropType<{ trim?: boolean, lazy?: boolean, number?: boolean }>,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'blur'],
|
||||
@@ -164,6 +170,8 @@ export default defineComponent({
|
||||
|
||||
const { emitFormBlur, emitFormInput, size, color, inputId, name } = useFormGroup(props, config)
|
||||
|
||||
const modelModifiers = ref(defu({}, props.modelModifiers, { trim: false, lazy: false, number: false }))
|
||||
|
||||
const input = ref<HTMLInputElement | null>(null)
|
||||
|
||||
const autoFocus = () => {
|
||||
@@ -172,11 +180,40 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const onInput = (event: InputEvent) => {
|
||||
emit('update:modelValue', (event.target as HTMLInputElement).value)
|
||||
// Custom function to handle the v-model properties
|
||||
const updateInput = (value: string) => {
|
||||
|
||||
if (modelModifiers.value.trim) {
|
||||
value = value.trim()
|
||||
}
|
||||
|
||||
if (modelModifiers.value.number || props.type === 'number') {
|
||||
value = looseToNumber(value)
|
||||
}
|
||||
|
||||
emit('update:modelValue', value)
|
||||
emitFormInput()
|
||||
}
|
||||
|
||||
const onInput = (event: InputEvent) => {
|
||||
if (!modelModifiers.value.lazy) {
|
||||
updateInput((event.target as HTMLInputElement).value)
|
||||
}
|
||||
}
|
||||
|
||||
const onChange = (event: InputEvent) => {
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
|
||||
if (modelModifiers.value.lazy) {
|
||||
updateInput(value)
|
||||
}
|
||||
|
||||
// Update trimmed input so that it has same behaviour as native input https://github.com/vuejs/core/blob/5ea8a8a4fab4e19a71e123e4d27d051f5e927172/packages/runtime-dom/src/directives/vModel.ts#L63
|
||||
if (modelModifiers.value.trim) {
|
||||
(event.target as HTMLInputElement).value = value.trim()
|
||||
}
|
||||
}
|
||||
|
||||
const onBlur = (event: FocusEvent) => {
|
||||
emitFormBlur()
|
||||
emit('blur', event)
|
||||
@@ -280,6 +317,7 @@ export default defineComponent({
|
||||
trailingIconClass,
|
||||
trailingWrapperIconClass,
|
||||
onInput,
|
||||
onChange,
|
||||
onBlur
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
v-bind="attrs"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -22,9 +23,10 @@
|
||||
import { ref, computed, toRef, watch, onMounted, nextTick, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { defu } from 'defu'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, looseToNumber } from '../../utils'
|
||||
import type { NestedKeyOf, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
@@ -119,6 +121,10 @@ export default defineComponent({
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
},
|
||||
modelModifiers: {
|
||||
type: Object as PropType<{ trim?: boolean, lazy?: boolean, number?: boolean }>,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'blur'],
|
||||
@@ -127,6 +133,8 @@ export default defineComponent({
|
||||
|
||||
const { emitFormBlur, emitFormInput, inputId, color, size, name } = useFormGroup(props, config)
|
||||
|
||||
const modelModifiers = ref(defu({}, props.modelModifiers, { trim: false, lazy: false, number: false }))
|
||||
|
||||
const textarea = ref<HTMLTextAreaElement | null>(null)
|
||||
|
||||
const autoFocus = () => {
|
||||
@@ -157,11 +165,38 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
// Custom function to handle the v-model properties
|
||||
const updateInput = (value: string) => {
|
||||
if (modelModifiers.value.trim) {
|
||||
value = value.trim()
|
||||
}
|
||||
|
||||
if (modelModifiers.value.number) {
|
||||
value = looseToNumber(value)
|
||||
}
|
||||
|
||||
emit('update:modelValue', value)
|
||||
emitFormInput()
|
||||
}
|
||||
|
||||
const onInput = (event: InputEvent) => {
|
||||
autoResize()
|
||||
if (!modelModifiers.value.lazy) {
|
||||
updateInput((event.target as HTMLInputElement).value)
|
||||
}
|
||||
}
|
||||
|
||||
emit('update:modelValue', (event.target as HTMLInputElement).value)
|
||||
emitFormInput()
|
||||
const onChange = (event: InputEvent) => {
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
|
||||
if (modelModifiers.value.lazy) {
|
||||
updateInput(value)
|
||||
}
|
||||
|
||||
// Update trimmed input so that it has same behaviour as native input
|
||||
if (modelModifiers.value.trim) {
|
||||
(event.target as HTMLInputElement).value = value.trim()
|
||||
}
|
||||
}
|
||||
|
||||
const onBlur = (event: FocusEvent) => {
|
||||
@@ -211,6 +246,7 @@ export default defineComponent({
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
textareaClass,
|
||||
onInput,
|
||||
onChange,
|
||||
onBlur
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,4 +56,13 @@ export function getSlotsChildren (slots: any) {
|
||||
return children
|
||||
}
|
||||
|
||||
/**
|
||||
* "123-foo" will be parsed to 123
|
||||
* This is used for the .number modifier in v-model
|
||||
*/
|
||||
export function looseToNumber (val: any): any {
|
||||
const n = parseFloat(val)
|
||||
return isNaN(n) ? val : n
|
||||
}
|
||||
|
||||
export * from './lodash'
|
||||
|
||||
Reference in New Issue
Block a user