Пользовательская валидация

Архитектура валидации в Inputmask

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

  • маска как ограничитель структуры
  • определения символов (definitions) как правила допустимых значений
  • поведенческие хуки (hooks) для динамической проверки
  • постобработка введённого значения
  • финальная проверка полноты (completion validation)

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


Определения символов как базовый уровень валидации

Ключевой механизм расширения Inputmask — объект definitions. Он задаёт, какие символы допустимы в каждом плейсхолдере маски.

Каждый символ маски может быть связан с объектом, содержащим правило проверки.

Inputmask.extendDefinitions({
  'A': {
    validator: "[A-Za-z]",
    cardinality: 1,
    definitionSymbol: "*"
  }
});

В этом примере:

  • A становится пользовательским токеном
  • validator определяет допустимый диапазон символов
  • cardinality задаёт количество символов, которые занимает правило
  • definitionSymbol влияет на отображение в маске

Функциональный валидатор

Помимо регулярных выражений, допускается использование функции:

Inputmask.extendDefinitions({
  'D': {
    validator: function (chrs, maskset, pos, strict, opts) {
      return parseInt(chrs, 10) % 2 === 0;
    },
    cardinality: 1
  }
});

Функциональный валидатор получает контекст:

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

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


Построение кастомных правил через mask options

Помимо расширения символов, Inputmask позволяет задавать уровень валидации на уровне всей маски.

Пост-валидация через postValidation

Хук postValidation применяется после первичной проверки маски и позволяет корректировать результат.

Inputmask({
  mask: "999-AAA",
  postValidation: function (buffer, currentResult, opts) {
    return buffer.join("").indexOf("000") === -1;
  }
}).mask(input);

В этом случае ввод отклоняется, если обнаружена запрещённая комбинация.


Проверка завершённости ввода

Одним из ключевых элементов пользовательской валидации является функция isComplete.

Она определяет, считается ли введённое значение валидным с точки зрения бизнес-логики.

Inputmask({
  mask: "9999-9999",
  isComplete: function (buffer, opts) {
    const value = buffer.join("");
    return value.replace(/[^0-9]/g, "").length === 8;
  }
});

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


Валидация при вводе: onBeforeWrite

Механизм onBeforeWrite позволяет вмешиваться в процесс записи символов до их фиксации в поле.

Inputmask({
  mask: "999-999",
  onBeforeWrite: function (event, buffer, caretPos, opts) {
    if (buffer.join("").startsWith("0")) {
      return false;
    }
  }
});

Возврат false блокирует изменение состояния, что делает этот хук инструментом жёсткой фильтрации.


Контроль ввода через onBeforePaste

Вставка данных часто нарушает ожидаемую структуру, поэтому используется отдельный механизм:

Inputmask({
  mask: "AA-9999",
  onBeforePaste: function (pastedValue, opts) {
    return pastedValue.toUpperCase().replace(/\s/g, "");
  }
});

Функция позволяет:

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

Событие incomplete как часть пользовательской валидации

Механизм onincomplete позволяет реагировать на незавершённые значения, которые не прошли финальную проверку.

Inputmask({
  mask: "999-999",
  onincomplete: function () {
    console.log("Значение не завершено");
  }
});

Это используется в сценариях, где важно различать:

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

Состояние complete и динамическая проверка

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

Inputmask({
  mask: "(999) 999-9999",
  oncomplete: function () {
    console.log("Ввод завершён корректно");
  }
});

Фактически это финальный слой, подтверждающий соответствие маске и пользовательским правилам.


Интеграция пользовательских правил с alias-масками

Alias-механизм Inputmask позволяет комбинировать встроенные типы масок с пользовательской логикой.

Inputmask.extendAliases({
  'custom-phone': {
    mask: "+7 (999) 999-99-99",
    isComplete: function (buffer) {
      return buffer.join("").indexOf("000") === -1;
    }
  }
});

Это позволяет создавать переиспользуемые схемы валидации, которые ведут себя как полноценные типы данных.


Контекстная валидация через состояние maskset

Для сложных сценариев используется доступ к внутреннему состоянию maskset.

Inputmask({
  mask: "9999-AAA",
  postValidation: function (buffer, result, opts) {
    const value = buffer.join("");
    const digits = value.replace(/\D/g, "");

    if (digits.length < 4) {
      return false;
    }

    return result;
  }
});

Такой подход позволяет учитывать:

  • частично введённые данные
  • позицию курсора
  • историческое состояние ввода

Многоуровневая стратегия пользовательской валидации

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

  1. символьные ограничения через definitions
  2. структурная маска
  3. поведенческие хуки (onBeforeWrite, onBeforePaste)
  4. логическая проверка через postValidation
  5. финальная проверка через isComplete
  6. события oncomplete / onincomplete

Каждый уровень не заменяет предыдущий, а дополняет его, формируя цепочку проверок от низкоуровневой фильтрации до бизнес-логики.


Кастомные валидаторы как основа расширяемости

Наиболее гибкий механизм — функция-валидатор внутри definitions. Он позволяет внедрять произвольную логику:

  • проверка диапазонов
  • контроль зависимых символов
  • валидация по внешним справочникам
  • контекстные ограничения
Inputmask.extendDefinitions({
  'X': {
    validator: function (chrs, maskset, pos, strict, opts) {
      const allowed = ["A", "B", "C"];
      return allowed.includes(chrs);
    },
    cardinality: 1
  }
});

Такая модель превращает Inputmask из инструмента форматирования в полноценный механизм контролируемого ввода данных.


Комбинирование пользовательской и системной логики

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

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

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