Проверка валидации

Механизм валидации в Inputmask строится вокруг идеи синхронизации пользовательского ввода с заранее определённой маской, где каждое изменение состояния поля немедленно проверяется на соответствие правилам. В отличие от классических схем, где валидация выполняется постфактум (например, при отправке формы), здесь проверка является непрерывным процессом, встроенным в поток ввода.

В основе лежит анализ каждого символа относительно позиции в маске, а также проверка допустимости переходов между состояниями. Маска выступает как формальный грамматический шаблон, а ввод пользователя — как поток токенов, который должен быть корректно сопоставлен этой грамматике.

Базовые принципы проверки корректности

Каждый символ, введённый пользователем, проходит несколько уровней проверки:

1. Проверка по маске символов Каждая позиция маски задаёт допустимый тип символа:

  • 9 — цифра
  • a — буква
  • * — буквенно-цифровой символ
  • фиксированные символы (-, /, (, ))

Ввод сравнивается с ожидаемым типом. Если символ не соответствует, он отклоняется или перенаправляется в следующую допустимую позицию (в зависимости от конфигурации).

2. Проверка позиции (position validation) Валидация учитывает не только сам символ, но и контекст его положения. Например, цифра может быть корректной по типу, но недопустимой в текущей позиции, если она нарушает структуру маски.

3. Проверка полного заполнения Поле считается валидным только в случае, если все обязательные позиции маски заполнены корректными символами.

Внутренний механизм isValid

Метод isValid() является центральной точкой проверки значения вне контекста ввода. Он используется для оценки строки целиком.

Алгоритм работы включает следующие этапы:

  • нормализация входной строки (удаление литералов маски при необходимости)
  • разбор строки в соответствии с определением маски
  • последовательное сопоставление каждого символа правилу позиции
  • проверка обязательных и необязательных сегментов

Особое внимание уделяется параметру greedy-маски, который влияет на строгость проверки.

Greedy-режим и его влияние на валидацию

Greedy-режим определяет, насколько строго Inputmask требует полного соответствия маске.

При включённом greedy:

  • все обязательные символы должны быть заполнены
  • незаполненные позиции автоматически считаются ошибкой
  • isComplete строго привязан к полной длине маски

При выключенном greedy:

  • допускаются частично заполненные значения
  • валидация становится «мягкой»
  • поле может считаться валидным даже при неполном вводе, если введённые символы корректны

Это особенно важно в формах с динамическими или необязательными полями.

Проверка регулярными выражениями

Inputmask использует внутреннюю трансляцию маски в регулярное выражение. Это позволяет проводить финальную проверку строки как единого объекта.

Процесс включает:

  • преобразование маски в regex-паттерн
  • добавление якорей начала и конца строки (^ и $)
  • учёт литералов и escape-символов
  • применение модификаторов (optional, repeat, group)

Таким образом, итоговая проверка часто сводится к:

  • либо поэлементной проверке
  • либо regex-валидации итогового значения

Маска как конечный автомат

С точки зрения теории автоматов, Inputmask можно представить как конечный автомат, где:

  • состояния — позиции маски
  • переходы — вводимые символы
  • правила перехода — mask definitions (9, a, *, regex-паттерны)
  • финальное состояние — полностью валидное поле

Каждый ввод символа вызывает переход автомата. Если переход невозможен, ввод блокируется или перенаправляется.

Такой подход объясняет высокую предсказуемость поведения Inputmask при сложных масках.

Проверка динамических масок

Динамические маски изменяют структуру в процессе ввода. В этом случае валидация становится двухуровневой:

  1. Валидация текущего состояния маски
  2. Валидация результата после потенциального изменения структуры

Например, при маске с условными блоками:

  • часть шаблона активируется только при определённом вводе
  • остальные блоки временно исключаются из проверки

Это требует пересчёта допустимых позиций после каждого изменения ввода.

Обработка вставки и буфера обмена

При вставке строки Inputmask не проверяет символы по одному, а анализирует всю вставку как единый фрагмент.

Алгоритм:

  • разбиение вставленного текста
  • сопоставление с текущей позицией маски
  • проверка каждого символа в контексте будущего состояния
  • откат изменений при несоответствии

Дополнительно применяются хук-функции, такие как onBeforePaste, позволяющие модифицировать строку до начала проверки.

Функции пред- и пост-валидации

Inputmask предоставляет несколько точек вмешательства в процесс проверки:

onBeforeValidate

Позволяет изменить входное значение до запуска основной валидации. Используется для:

  • нормализации формата
  • удаления лишних символов
  • преобразования локальных форматов

onBeforePaste

Работает с буфером обмена до вставки. Часто применяется для:

  • очистки форматирования
  • удаления пробелов
  • преобразования разделителей

onValidationComplete

Срабатывает после завершения проверки текущего состояния. Позволяет:

  • фиксировать валидность
  • запускать дополнительную бизнес-логику
  • обновлять состояние UI

Частичная валидность и маски с опциональными сегментами

Маски могут содержать необязательные части, обозначаемые специальными конструкциями ([], {} или альтернативными паттернами).

В таких случаях валидация учитывает:

  • обязательные сегменты (must match)
  • опциональные сегменты (may match)
  • альтернативные ветки (OR-логика)

Это приводит к появлению нескольких допустимых валидных состояний одной и той же маски.

Контроль завершённости ввода

Система различает два состояния:

  • валидность (validity) — соответствие введённых символов правилам
  • завершённость (completeness) — полное заполнение всех обязательных позиций

Поле может быть:

  • валидным, но незавершённым
  • завершённым, но невалидным (редко, при нестандартных конфигурациях)
  • валидным и завершённым одновременно

Проверка завершённости особенно важна для форм с обязательной отправкой.

Инкрементальная проверка

Одной из ключевых особенностей является инкрементальная валидация. Вместо полной проверки строки после каждого изменения используется:

  • проверка только изменённой позиции
  • локальная корректировка состояния
  • пересчёт зависимых сегментов

Это снижает вычислительную нагрузку и делает Inputmask пригодным для высокочастотного ввода.

Обработка ошибок валидации

Ошибки валидации не выражаются как исключения. Вместо этого система использует мягкие механизмы:

  • игнорирование символа
  • автоматическое перемещение курсора
  • замена символа на допустимый
  • откат последнего действия

Такой подход позволяет избежать прерывания потока ввода.

Сравнение состояния маски и реального значения

Внутри Inputmask поддерживается два представления:

  • raw value (сырое значение без форматирования)
  • formatted value (значение с маской)

Валидация может выполняться как на одном уровне, так и на обоих. Например:

  • formatted value проверяется на структуру
  • raw value проверяется на смысловую корректность

Это особенно важно для финансовых, телефонных и идентификационных форматов.

Поведение при конфликте правил

Если несколько правил маски конфликтуют (например, пересекающиеся регулярные выражения), применяется приоритет:

  1. фиксированные символы
  2. строгие масочные правила (9, a)
  3. regex-правила
  4. fallback-логика

Конфликты не приводят к ошибке выполнения, но могут ограничивать допустимые вводы.

Контекстная валидация и зависимости

Некоторые маски требуют учёта контекста предыдущих символов. Например:

  • проверка длины сегмента
  • зависимость формата от первых символов
  • условные ветвления

В таких случаях валидация становится контекстно-зависимой и не может быть сведена к простому regex.

Итоговая модель проверки

В обобщённом виде процесс проверки в Inputmask можно представить как последовательность:

  • анализ символа
  • сопоставление с правилом позиции
  • проверка контекста
  • обновление состояния автомата
  • инкрементальная переоценка валидности
  • финальная проверка завершённости при необходимости

Такой многоуровневый подход обеспечивает устойчивость системы к нестандартному вводу и делает возможной работу сложных масок без потери интерактивности.