2
0
mirror of https://github.com/tenrok/maska.git synced 2026-06-20 20:00:34 +03:00

Make directive change async for correct eager mode

Fix #133 where eager mask used with v-model
This commit is contained in:
Alexander Shabunevich
2023-02-11 16:12:15 +03:00
parent df99482c70
commit 359f446d72
4 changed files with 24 additions and 20 deletions
+7 -14
View File
@@ -6,13 +6,11 @@ type MaskaDirective = Directive<HTMLElement, MaskaDetail | undefined>
const masks = new WeakMap<HTMLInputElement, MaskInput>() const masks = new WeakMap<HTMLInputElement, MaskInput>()
const checkValue = (input: HTMLInputElement): void => { const checkValue = (input: HTMLInputElement): void => {
const value = input.dataset.maskaValue setTimeout(() => {
if ( if (masks.get(input)?.needUpdateValue(input) === true) {
(value == null && input.value !== '') || input.dispatchEvent(new CustomEvent('input'))
(value != null && value !== input.value) }
) { })
input.dispatchEvent(new CustomEvent('input'))
}
} }
export const vMaska: MaskaDirective = (el, binding) => { export const vMaska: MaskaDirective = (el, binding) => {
@@ -21,10 +19,10 @@ export const vMaska: MaskaDirective = (el, binding) => {
if (input == null) return if (input == null) return
checkValue(input)
const existed = masks.get(input) const existed = masks.get(input)
if (existed != null) { if (existed != null) {
checkValue(input)
if (!existed.needUpdateOptions(input, opts)) { if (!existed.needUpdateOptions(input, opts)) {
return return
} }
@@ -49,9 +47,4 @@ export const vMaska: MaskaDirective = (el, binding) => {
} }
masks.set(input, new MaskInput(input, opts)) masks.set(input, new MaskInput(input, opts))
// timeout to process initial v-model value
setTimeout(() => {
checkValue(input)
})
} }
+9 -1
View File
@@ -50,6 +50,15 @@ export class MaskInput {
return JSON.stringify(mask.opts) !== JSON.stringify(maskNew.opts) return JSON.stringify(mask.opts) !== JSON.stringify(maskNew.opts)
} }
needUpdateValue (input: HTMLInputElement): boolean {
const value = input.dataset.maskaValue
return (
(value == null && input.value !== '') ||
(value != null && value !== input.value)
)
}
private getMaskOpts (options: MaskInputOptions): MaskOptions { private getMaskOpts (options: MaskInputOptions): MaskOptions {
const { onMaska, preProcess, postProcess, ...opts } = options const { onMaska, preProcess, postProcess, ...opts } = options
@@ -98,7 +107,6 @@ export class MaskInput {
const input = e.target as HTMLInputElement const input = e.target as HTMLInputElement
const mask = this.items.get(input) as Mask const mask = this.items.get(input) as Mask
const valueOld = input.value const valueOld = input.value
const ss = input.selectionStart const ss = input.selectionStart
const se = input.selectionEnd const se = input.selectionEnd
+3 -3
View File
@@ -2,10 +2,10 @@
import { ref } from 'vue' import { ref } from 'vue'
import { vMaska } from '../../src' import { vMaska } from '../../src'
const data = ref('123') const data = ref('1234')
</script> </script>
<template> <template>
<input v-maska data-maska="#-#" v-model="data" /> <input v-maska data-maska="##-#" v-model="data" data-maska-eager />
<button @click="data = '345'">Set</button> <button @click="data = '5678'">Set</button>
</template> </template>
+5 -2
View File
@@ -138,17 +138,20 @@ test('custom component', async () => {
expect(wrapper.get('div').element.textContent).toBe('1-2') expect(wrapper.get('div').element.textContent).toBe('1-2')
}) })
// TODO: find a way to test keyboard input, like backspace after input '567'
test('change value', async () => { test('change value', async () => {
const wrapper = mount(ChangeValue) const wrapper = mount(ChangeValue)
const input = wrapper.get('input') const input = wrapper.get('input')
await new Promise((r) => setTimeout(r)) await new Promise((r) => setTimeout(r))
expect(input.element.value).toBe('1-2') expect(input.element.value).toBe('12-3')
await wrapper.get('button').trigger('click') await wrapper.get('button').trigger('click')
expect(input.element.value).toBe('3-4') await new Promise((r) => setTimeout(r))
expect(input.element.value).toBe('56-7')
}) })
test('multiple inputs', async () => { test('multiple inputs', async () => {