Маски ввода создают дополнительный слой логики между пользователем и DOM-элементом. Во время ввода символов библиотека:
Из-за этого ошибки в масках часто выглядят неочевидно:
input.value отличается от ожидаемого.Отладка Inputmask требует понимания внутренних механизмов библиотеки и последовательности обработки ввода.
Наиболее распространённая категория проблем связана с неверными опциями.
Пример:
Inputmask({
mask: "99/99/9999",
greedy: false,
repeat: 10
}).mask(input);
Опция repeat не имеет смысла для фиксированной маски и
может приводить к неожиданному поведению.
Другой пример:
Inputmask({
alias: "numeric",
groupSeparator: ",",
radixPoint: ","
}).mask(input);
Использование одинакового символа для разделителя групп и десятичной части приводит к конфликту парсинга.
Маска может быть уничтожена или потеряна после:
innerHTML;Пример проблемы:
container.innerHTML = `
<input id="phone">
`;
Inputmask("+7 (999) 999-99-99").mask("#phone");
После повторного изменения innerHTML маска исчезнет,
потому что DOM-элемент заменяется новым экземпляром.
Inputmask активно использует:
keydownkeypressinputpastecompositionblurfocusЕсли поверх поля добавляются собственные обработчики, возможны конфликты.
Пример:
input.addEventListener("input", () => {
input.value = input.value.toUpperCase();
});
Такой код вмешивается в работу внутреннего буфера Inputmask.
Следствия:
Особенно часто проблемы возникают в:
Причина — конфликт между виртуальным DOM и прямой модификацией поля библиотекой Inputmask.
Пример для React:
<input value={value} onCha nge={handleChange} />
Inputmask изменяет DOM напрямую, а React затем пытается восстановить собственное состояние.
Результат:
После применения маски экземпляр сохраняется внутри DOM-элемента.
Проверка:
console.log(input.inputmask);
Можно исследовать:
console.log(input.inputmask.opts);
console.log(input.inputmask.unmaskedvalue());
console.log(input.inputmask.isComplete());
Это позволяет быстро понять:
Inputmask хранит внутренний буфер символов.
Получение буфера:
console.log(input.inputmask.maskset.buffer);
Пример результата:
[
"1",
"2",
"/",
"0",
"5",
"/",
"_",
"_",
"_",
"_"
]
Буфер помогает диагностировать:
Внутренняя структура:
console.log(input.inputmask.maskset);
Содержит:
Особенно полезно поле:
validPositions
Пример:
console.log(
input.inputmask.maskset.validPositions
);
Оно показывает, какие символы реально приняты маской.
Критически важно понимать последовательность событий.
Пример:
[
"keydown",
"keypress",
"input",
"keyup",
"blur"
].forEach(eventName => {
input.addEventListener(eventName, event => {
console.log(eventName, event.target.value);
});
});
Позволяет обнаружить:
Многие ошибки возникают из-за путаницы между отображаемым и чистым значением.
Пример:
input.value
Результат:
+7 (999) 123-45-67
Но:
input.inputmask.unmaskedvalue()
Результат:
9991234567
Если backend ожидает одно значение, а отправляется другое — появляются ошибки валидации.
Опция:
removeMaskOnSubmit: true
Изменяет данные формы непосредственно перед submit.
Проблемы:
Проверка:
form.addEventListener("submit", event => {
console.log(input.value);
});
Inputmask постоянно управляет курсором.
Типичные симптомы:
console.log(
input.selectionStart,
input.selectionEnd
);
Во время событий:
input.addEventListener("input", () => {
console.log(input.selectionStart);
});
Ошибка:
input.setSelectionRange(0, 0);
Если код вызывается одновременно с внутренней логикой Inputmask, курсор начинает вести себя нестабильно.
Особенно опасны:
setTimeout;Inputmask имеет собственную обработку вставки.
Проверка содержимого:
input.addEventListener("paste", event => {
console.log(
event.clipboardData.getData("text")
);
});
Часто проблема связана с неожиданными символами.
Пример:
+7 999 123-45-67
Здесь может использоваться:
Диагностика:
const text = event.clipboardData.getData("text");
console.log(
[...text].map(char => char.charCodeAt(0))
);
Пример:
mask: "(999) 999[-9999]"
Inputmask должен определить:
Такие маски часто вызывают сложные баги.
Полезно включать:
clearIncomplete: false
И анализировать:
console.log(
input.inputmask.isComplete()
);
Наиболее нестабильная категория масок:
Inputmask("numeric", {
digits: 2,
radixPoint: ",",
groupSeparator: " "
});
Причины:
console.log(
input.inputmask.unmaskedvalue()
);
Результат может отличаться от визуального значения.
Например:
123456
вместо:
123 456,00
Опция:
autoGroup: true
Иногда вызывает проблемы с caret.
Особенно:
Диагностика:
autoGroup: false
Если ошибка исчезает — проблема связана с группировкой.
Пример:
mask: [
"+7 (999) 999-99-99",
"+1 (999) 999-9999"
]
Inputmask автоматически выбирает шаблон.
Проблемы:
Проверка:
console.log(
input.inputmask.maskset
);
Особенно полезны:
tests;jitOffset;validPositions.Очень полезно для диагностики входных данных.
Пример:
Inputmask({
mask: "+7 (999) 999-99-99",
onBeforeMask(value) {
console.log(value);
return value.replace(/\D/g, "");
}
});
Позволяет увидеть:
Inputmask({
mask: "+7 (999) 999-99-99",
onBeforePaste(value) {
console.log(value);
return value.replace(/\D/g, "");
}
});
Позволяет диагностировать:
Inputmask({
mask: "99/99/9999",
oncomplete() {
console.log("complete");
},
onincomplete() {
console.log("incomplete");
}
});
Часто помогает обнаружить:
Ошибка:
Inputmask(mask).mask(input);
Inputmask(mask).mask(input);
Маска инициализируется повторно поверх существующей.
Следствия:
if (input.inputmask) {
input.inputmask.remove();
}
После этого:
Inputmask(mask).mask(input);
Признаки:
Пример:
regex: "([0-9]{1,10}|[A-Z]{1,10})*"
Сложные регулярные выражения резко увеличивают стоимость проверки.
Пример:
mask: [
"999999999",
"AAAAAAAAA",
"***-***-***",
...
]
Каждый ввод требует перебора вариантов.
Ошибка:
setInterval(() => {
Inputmask(mask).mask(input);
}, 100);
Маска создаётся заново десятки раз в секунду.
Плохой пример:
<input
value={value}
onCha nge={e => setValue(e.target.value)}
/>
Inputmask и React одновременно контролируют поле.
const ref = useRef();
useEffect(() => {
Inputmask("+7 (999) 999-99-99")
.mask(ref.current);
}, []);
return <input ref={ref} />;
Важно удалять маску:
useEffect(() => {
const instance = new Inputmask(mask);
instance.mask(ref.current);
return () => {
ref.current.inputmask?.remove();
};
}, []);
Пример конфликта:
<input v-model="phone">
Inputmask меняет DOM, а Vue синхронизирует значение обратно.
mounted() {
Inputmask(mask).mask(this.$refs.phone);
}
Мобильные клавиатуры:
input.addEventListener("input", event => {
console.log(event.inputType);
});
Например:
insertText
deleteContentBackward
insertFromPaste
Опасный код:
input.addEventListener("input", async () => {
await save();
input.value = normalize(input.value);
});
Пока выполняется await, состояние Inputmask уже
изменилось.
Один из лучших способов диагностики — постепенное упрощение маски.
Исходная конфигурация:
Inputmask({
alias: "numeric",
digits: 2,
autoGroup: true,
groupSeparator: " ",
radixPoint: ",",
rightAlign: false,
nullable: false,
clearIncomplete: true,
placeholder: "0"
});
Минимальный вариант:
Inputmask("numeric");
Если проблема исчезает, опции добавляются постепенно до обнаружения источника ошибки.
console.log(input);
console.log(input.inputmask);
input.addEventListener("input", console.log);
console.log(input.value);
console.log(input.inputmask.unmaskedvalue());
console.log(
input.inputmask.maskset.buffer
);
Необходимо временно удалить:
Inputmask("9999").mask(input);
Если ошибка исчезает, проблема связана со сложностью исходной конфигурации.