I have an issue with vue-imask in Vue 3 using the setup script, I tried resetting both my npm and pnpm caches (I am using pnpm in my project), but neither seemed to fix the issue.
The problem arises as soon as I try to redefine the default blocks for the date mask, d, m and Y.
This is a simplified version of my code:
<template>
<BsdkInputText
v-bind="$props.inputProps"
v-model="value"
:mask="$props.inputProps?.mask || mask"
@click="togglePopover"
/>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { IMask } from 'vue-imask'
import type { FactoryArg } from 'imask'
const value = defineModel<string | null>()
const pattern = computed(() => {
// Get the user's locale
const userLocale = navigator.language
// Create a date format using the user's locale
const dateFormat = new Intl.DateTimeFormat(userLocale)
// Get the format parts (e.g., day, month, year)
const formatParts = dateFormat.formatToParts(new Date())
// Create a mask pattern based on the format parts
const maskPattern = formatParts.map((part) => {
switch (part.type) {
case 'day': return 'd'
case 'month': return 'm'
case 'year': return 'Y'
case 'literal': return '/'
default: return part.value
}
}).join('')
return maskPattern
})
const mask = {
mask: Date,
lazy: false,
pattern: pattern.value,
blocks: {
d: {
mask: IMask.MaskedRange,
from: 1,
to: 31,
maxLength: 2,
},
m: {
mask: IMask.MaskedRange,
from: 1,
to: 12,
maxLength: 2,
},
Y: {
mask: IMask.MaskedRange,
from: 1900,
to: 9999,
},
},
format: (date: Date) => {
let day: string | number = date.getDate()
let month: string | number = date.getMonth() + 1
const year: string | number = date.getFullYear()
if (day < 10) {
day = `0${day}`
}
if (month < 10) {
month = `0${month}`
}
return `${day}/${month}/${year}`
},
parse: (str: string) => {
const [day, month, year] = str.split('/')
return new Date(+year, +month - 1, +day)
},
min: props.minDate,
max: props.maxDate,
autofix: true,
} as FactoryArg
</script>
And this is my BsdkInputText component:
<template>
<input
:id
v-imask="mask"
:value="modelValue"
:type
:class="mergedInputClasses"
:placeholder
:required="field.required"
:disabled="field.disabled"
@accept="onAccept"
@complete="onComplete"
@input="onUpdateModelValue"
>
</template>
<script setup lang="ts">
import { type Ref, computed, inject, ref } from 'vue'
import type { ClassEntries } from '@binarysystem/bsdk-ui-tailwind-merge'
import { useTailwindMerge } from '@binarysystem/bsdk-ui-tailwind-merge'
import { IMaskDirective as vImask } from 'vue-imask'
import type { Field } from '@binarysystem/bsdk-ui-form-field'
import type { FactoryArg } from 'imask'
export interface Props {
id: string
modelValue?: string | null
type?: string
placeholder?: string
required?: boolean
disabled?: boolean
invalid?: boolean
inputClasses?: ClassEntries
mask?: FactoryArg
}
const props = withDefaults(defineProps<Props>(), {
type: 'text',
required: false,
disabled: false,
invalid: false,
})
const emit = defineEmits(['update:modelValue'])
const field = inject<Ref<Field>>('field', ref(props))
const { mergeClasses } = useTailwindMerge()
const mergedInputClasses = computed(() => {
// Tailwind classes logic
})
function onAccept (e: any) {
const maskRef = e.detail
emit('update:modelValue', maskRef.value)
}
function onComplete (e: any) {
const maskRef = e.detail
emit('update:modelValue', maskRef.value)
}
function onUpdateModelValue (e: any) {
if (props.mask) {
return
}
emit('update:modelValue', e.target.value)
}
</script>
First, I had to use a hack to make the v-imask directive work in Vue 3 while using the setup script, since I tried adding it to the app instance using the following, but there was a problem with types:
import type { App } from 'vue'
import '@assets/stylesheets/main.css'
import { IMaskDirective } from 'vue-imask'
import BsdkDatePicker from '@/components/BsdkDatePicker.vue'
import 'v-calendar/style.css'
export { BsdkDatePicker }
export default {
install: (app: App) => {
app.component('BsdkDatePicker', BsdkDatePicker)
app.directive('imask', IMaskDirective)
},
}
And this was the TypeScript error:
Argument of type '{ [x: string]: string | (<Opts extends FactoryArg>(el: DirectiveMaskElement<Opts>, { value: options }: { value: Opts; }) => void); name: string; }' is not assignable to parameter of type 'Directive<any, any>'.
Type '{ [x: string]: string | (<Opts extends FactoryArg>(el: DirectiveMaskElement<Opts>, { value: options }: { value: Opts; }) => void); name: string; }' has no properties in common with type 'ObjectDirective<any, any>'.ts(2345
Anyway, the real problem is that I get the Class constructor x cannot be invoked without "new" error as soon as I try to redefine the default date blocks.
Is this caused by the way I am using the vue-imask plugin, a misuse of the blocks in the mask, or anything else?
Note that if I try to remove the definition of the blocks and use the default ones, everything works correctly, but I wanted to define the blocks to have a placeholder like this DD/MM/YYYY instead of the default one __/__/____.
Please let me know, and thanks in advance.
Versions:
vue-imaks: 7.6.1
vue: 3.4.27
@storybook/vue3: 8.1.5 (I am using Storybook to test the component)
I have an issue with
vue-imask
in Vue 3 using the setup script, I tried resetting both mynpm
andpnpm
caches (I am usingpnpm
in my project), but neither seemed to fix the issue.The problem arises as soon as I try to redefine the default blocks for the date mask,
d
,m
andY
.This is a simplified version of my code:
And this is my
BsdkInputText
component:First, I had to use a hack to make the
v-imask
directive work in Vue 3 while using the setup script, since I tried adding it to the app instance using the following, but there was a problem with types:And this was the TypeScript error:
Anyway, the real problem is that I get the
Class constructor x cannot be invoked without "new"
error as soon as I try to redefine the default date blocks. Is this caused by the way I am using thevue-imask
plugin, a misuse of the blocks in the mask, or anything else?Note that if I try to remove the definition of the blocks and use the default ones, everything works correctly, but I wanted to define the blocks to have a placeholder like this
DD/MM/YYYY
instead of the default one__/__/____
.Please let me know, and thanks in advance.
Versions:
7.6.1
3.4.27
8.1.5
(I am using Storybook to test the component)Originally posted by @DenisLantero in https://github.com/uNmAnNeR/imaskjs/discussions/1012#discussioncomment-10161119