Skip to content

Commit 6373d14

Browse files
committed
feat: allow v-model.lazy
emit `@input` and `@change`
1 parent 7fb0423 commit 6373d14

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

src/BaseInput.vue

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,23 @@
1414
<input
1515
v-if="type !== 'textarea'"
1616
ref="inputRef"
17-
v-model="value"
17+
:value="value"
1818
:type="type"
1919
data-testid="base-input-input"
2020
:class="theme.input"
2121
v-bind="inputAttrs"
2222
@change="handleChange"
23+
@input="handleInput"
2324
>
2425
<textarea
2526
v-if="type === 'textarea'"
2627
ref="inputRef"
27-
v-model="value"
28+
:value="value"
2829
:class="theme.input"
2930
data-testid="base-input-textarea"
3031
v-bind="textareaAttrs"
3132
@change="handleChange"
33+
@input="handleInput"
3234
/>
3335
<div
3436
v-if="$slots.suffix"
@@ -42,7 +44,7 @@
4244

4345
<script setup lang="ts">
4446
import type {InputHTMLAttributes, PropType, TextareaHTMLAttributes} from 'vue'
45-
import {computed, ref, watch} from 'vue'
47+
import {computed, ref} from 'vue'
4648
import type {InputClass, InputType} from './interface'
4749
import useMergedClassesRef from './utils/useMergedClasses'
4850
@@ -63,6 +65,10 @@ const props = defineProps({
6365
type: String as PropType<InputType>,
6466
default: 'text',
6567
},
68+
modelModifiers: {
69+
type: Object as PropType<Record<'lazy', boolean>>,
70+
default: () => ({}),
71+
},
6672
})
6773
6874
// TODO: temporary workaround for https://github.com/vuejs/core/pull/6294
@@ -78,30 +84,18 @@ const theme = useMergedClassesRef(props.classes)
7884
7985
const inputRef = ref<HTMLInputElement | null>(null)
8086
81-
const internalModel = ref<undefined | number | string>(undefined)
82-
8387
const emit = defineEmits<{
8488
(e: 'update:modelValue', value: typeof props.modelValue): void
8589
(e: 'change', event: Event): void
90+
(e: 'input', event: Event): void
8691
}>()
8792
88-
const isUncontrolled = computed(() => props.modelValue === undefined)
89-
90-
watch(props, (p) => {
91-
if (p.modelValue === undefined)
92-
internalModel.value = undefined
93-
})
94-
9593
const value = computed<string | number | undefined>({
9694
get() {
97-
if (!isUncontrolled.value)
98-
return props.modelValue
99-
else
100-
return internalModel.value
95+
return props.modelValue
10196
},
10297
set(value) {
10398
emit('update:modelValue', value)
104-
internalModel.value = value
10599
},
106100
})
107101
@@ -124,14 +118,28 @@ const handleWrapperClick = () => {
124118
focusInput()
125119
}
126120
127-
const handleChange = (e: Event) => {
128-
emit('change', e)
129-
}
121+
const isLazy = computed(() => !!props.modelModifiers.lazy)
130122
131123
defineExpose({
132124
focus: focusInput,
133125
blur: blurInput,
134126
select: selectInput,
135127
})
136128
129+
const handleChange = (e: Event) => {
130+
emit('change', e)
131+
if (isLazy.value) {
132+
const target = e.target as HTMLTextAreaElement | HTMLInputElement
133+
value.value = target.value
134+
}
135+
}
136+
137+
const handleInput = (e: Event) => {
138+
emit('input', e)
139+
if (!isLazy.value) {
140+
const target = e.target as HTMLTextAreaElement | HTMLInputElement
141+
value.value = target.value
142+
}
143+
}
144+
137145
</script>

src/tests/base-input.cy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,5 +243,9 @@ describe('<BaseInput />', () => {
243243
cy.get(inputSelector).should('have.value', defaultValueText)
244244
cy.get(inputTesterValueSelector).should('have.text', defaultValueText)
245245
})
246+
247+
it('test', () => {
248+
mount(BaseInput)
249+
})
246250
})
247251

0 commit comments

Comments
 (0)