Skip to content

Vue ​

Директива v-mask из tinyval-mask/vue вешает маску на поле. Сам Vue пакету не нужен: директива — обычный объект, Vue используется только для типов.

vue
<script setup lang="ts">
import { ref } from 'vue';
import { phone, money } from 'tinyval-mask/presets';
import { vMask } from 'tinyval-mask/vue';

// create masks once, not inline in the template
const phoneMask = phone();
const moneyMask = money({ currency: '₽' });

const tel = ref('');
const amount = ref('');
</script>

<template>
  <input v-model="tel" v-mask="phoneMask" />
  <input v-model="amount" v-mask="moneyMask" inputmode="decimal" />
  <input v-mask="'99.99.9999'" />
</template>
  • В v-model попадает значение с маской: +7 (999) 123-45-67. Чтобы получить значение без маски, добавьте модификатор .raw — см. ниже.
  • Маску создавайте в <script>: выражение вроде v-mask="phone()" создаёт новую маску при каждой перерисовке.
  • Директиву можно повесить на обёртку — она найдёт <input> внутри. Так маска работает с полями UI-библиотек.
  • Для глобальной регистрации: app.directive('mask', vMask).

Значение без маски — .raw ​

С модификатором .raw в поле видна маска, а в v-model попадает значение без неё — то же, что вернул бы unmask. Его можно сразу сохранять:

vue
<input v-model="tel" v-mask.raw="phoneMask" />    <!-- tel: '79991234567' -->
<input v-model="amount" v-mask.raw="moneyMask" /> <!-- amount: '1500.5' -->

Значение из модели показывается с маской: tel = '79991234567' → в поле +7 (999) 123-45-67. Курсор при правке в середине не прыгает, даже когда Vue перерисовывает поле.

Видимый шаблон ​

Передайте символ-заполнитель — при фокусе в поле появится весь шаблон, курсор встанет на первую пустую позицию:

vue
<input v-model="tel" v-mask.raw="{ mask: phoneMask, placeholder: '_' }" placeholder="Phone" />
<!-- on focus: +7 (___) ___-__-__   typing: +7 (999) 12_-__-__ -->
  • В v-model шаблон не попадает: без .raw там +7 (999) 12, с .raw — 7999912.
  • Пустое поле при уходе очищается — видна обычная подсказка placeholder. Частично заполненное сохраняет шаблон.
  • У числовых масок шаблона нет: их длина не фиксирована.

С tinyval-vue ​

v-mask работает на <TvField> и на любом поле формы tinyval-vue. С .raw в форму сразу попадают цифры, и схема проверяет их без unmask:

vue
<script setup lang="ts">
import { object, string, pipe, length } from 'tinyval';
import { useForm, TvForm, TvField, TvError } from 'tinyval-vue';
import { phone } from 'tinyval-mask/presets';
import { vMask } from 'tinyval-mask/vue';

const phoneMask = phone();

const Contact = object({
  phone: pipe(string(), length(11)),
});

const form = useForm(Contact, { initial: { phone: '' } });
</script>

<template>
  <TvForm :form="form" @submit="(data) => api.post('/contacts', data)">
    <TvField name="phone" v-mask.raw="{ mask: phoneMask, placeholder: '_' }" inputmode="tel" />
    <TvError name="phone" />
  </TvForm>
</template>

В поле — +7 (999) 123-45-67, в form.values.phone и в data — 79991234567.

UI-библиотеки ​

vue
<el-input v-model="tel" v-mask="phoneMask" />
<v-text-field v-model="tel" v-mask="phoneMask" />

См. также ​