Работа с множественными полями

Библиотека Validator.js изначально ориентирована на проверку строковых значений, однако в реальных приложениях часто возникает необходимость работать с наборами данных: списками email-адресов, массивами телефонов, динамическими формами и вложенными структурами. В таких случаях базовые функции библиотеки дополняются логикой обхода коллекций и агрегации результатов валидации.

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


Валидация массивов простых значений

При работе с массивами строк Validator.js применяется через итерацию по элементам. Каждое значение проходит стандартные проверки, такие как isEmail, isLength, isNumeric.

import validator from 'validator';

const emails = [
  'user@example.com',
  'invalid-email',
  'admin@site.org'
];

const results = emails.map(email => validator.isEmail(email));

Такой подход позволяет сохранить простоту API библиотеки, поскольку Validator.js не требует специальной поддержки массивов — обработка выполняется на уровне приложения.

Расширенная проверка часто включает фильтрацию корректных и некорректных значений:

const validEmails = emails.filter(email => validator.isEmail(email));
const invalidEmails = emails.filter(email => !validator.isEmail(email));

Проверка списков email, телефонов и других однотипных данных

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

const phones = [
  '+77001234567',
  '87001234567',
  'invalid-phone'
];

const normalizedPhones = phones.map(phone => validator.trim(phone));

const validPhones = normalizedPhones.filter(phone =>
  validator.isMobilePhone(phone, 'any')
);

В подобных сценариях применяется предварительная нормализация, включающая удаление пробелов, приведение формата и фильтрацию пустых значений.


Обработка динамических форм

В динамических формах количество полей заранее неизвестно. Например, пользователь может добавлять произвольное число контактов или адресов. В таких случаях структура данных представляет собой массив объектов.

const formData = {
  users: [
    { email: 'first@example.com', age: '25' },
    { email: 'wrong-email', age: '17' }
  ]
};

Проверка выполняется через обход массива и валидацию каждого поля объекта:

const errors = [];

formData.users.forEach((user, index) => {
  if (!validator.isEmail(user.email)) {
    errors.push({ index, field: 'email' });
  }

  if (!validator.isInt(user.age, { min: 18 })) {
    errors.push({ index, field: 'age' });
  }
});

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


Пользовательские функции для коллекций

Стандартный набор Validator.js не включает встроенные средства для работы с массивами, поэтому часто создаются вспомогательные функции.

function validateArray(array, validateFn) {
  return array.map((value, index) => ({
    index,
    valid: validateFn(value)
  }));
}

Применение:

const result = validateArray(emails, validator.isEmail);

Более сложные сценарии включают комбинированную проверку:

function validateUsers(users) {
  return users.map(user => ({
    email: validator.isEmail(user.email),
    age: validator.isInt(user.age, { min: 18 })
  }));
}

Комбинирование с преобразованием данных

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

const rawValues = [' 10 ', '20', ' 30'];

const numbers = rawValues
  .map(value => validator.trim(value))
  .map(value => Number(value));

const validNumbers = numbers.filter(value =>
  validator.isInt(String(value))
);

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


Агрегация ошибок для множественных полей

При работе с коллекциями данных важно формировать структурированный результат ошибок. Вместо простого булевого результата используется объект, содержащий подробную информацию.

const errors = {};

emails.forEach((email, index) => {
  if (!validator.isEmail(email)) {
    errors[index] = 'Некорректный email';
  }
});

Более универсальная структура включает группировку по полям:

const errors = {
  emails: [],
  phones: []
};

emails.forEach((email, index) => {
  if (!validator.isEmail(email)) {
    errors.emails.push(index);
  }
});

Такой формат упрощает интеграцию с интерфейсами форм, где ошибки отображаются на уровне конкретных полей.


Обработка вложенных структур и массивов объектов

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

const data = {
  orders: [
    {
      id: '1',
      amount: '100',
      email: 'client@example.com'
    },
    {
      id: '2',
      amount: 'invalid',
      email: 'wrong-email'
    }
  ]
};

Проверка:

const result = data.orders.map(order => ({
  id: order.id,
  amountValid: validator.isNumeric(order.amount),
  emailValid: validator.isEmail(order.email)
}));

При необходимости добавляется агрегация общего состояния:

const hasErrors = result.some(r => !r.amountValid || !r.emailValid);

Масштабируемые паттерны обработки коллекций

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

const rules = {
  email: validator.isEmail,
  age: value => validator.isInt(value, { min: 18 })
};

function validateObject(obj, rules) {
  const result = {};

  Object.keys(rules).forEach(key => {
    result[key] = rules[key](obj[key]);
  });

  return result;
}

Для массивов объектов:

const validated = users.map(user => validateObject(user, rules));

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