Отправка данных формы

Формирование значений при сабмите формы в AutoNumeric напрямую зависит от того, в каком виде библиотека хранит данные в DOM. Ключевая особенность заключается в разделении отображаемого значения и «чистого» числового представления, которое используется при обработке данных на стороне клиента или сервера.

При использовании AutoNumeric значение в input-поле визуально форматируется: добавляются разделители тысяч, задаётся символ валюты, управляются десятичные знаки. Однако фактическое число внутри экземпляра остаётся доступным в необработанном виде и может быть извлечено без форматирования.

AutoNumeric поддерживает несколько способов получения данных:

  • отображаемое значение (formatted value)
  • числовое значение (numeric value)
  • строковое «сырое» значение без форматирования

Ключевые методы экземпляра:

  • getNumericString() — возвращает число в виде строки без форматирования
  • getNumber() — возвращает число как JavaScript Number
  • getFormatted() — возвращает отображаемое значение с разделителями и символами

Это разделение критически важно при отправке формы, поскольку стандартный form.submit() отправляет именно содержимое DOM-элементов, а не внутренние представления библиотеки.

Проблема стандартной отправки формы

При использовании обычной HTML-формы браузер отправляет значение input «как есть»:

<form id="paymentForm">
  <input id="amount" name="amount">
  <button type="submit">Send</button>
</form>

Если поле amount контролируется AutoNumeric и отображает, например, 1 234,56 €, то именно эта строка попадёт в payload запроса.

Это создаёт несколько проблем:

  • сервер вынужден разбирать форматированные строки
  • локализация (запятая/точка) ломает парсинг
  • символы валюты мешают конвертации в число
  • пробелы и неразрывные пробелы требуют очистки

Использование чистого значения при сабмите

Наиболее устойчивый подход — перехват события отправки формы и извлечение числовых значений через API AutoNumeric.

const amountElement = document.querySelector('#amount');
const anAmount = AutoNumeric.getAutoNumericElement(amountElement);

document.querySelector('#paymentForm').addEventListener('submit', (e) => {
  e.preventDefault();

  const rawValue = anAmount.getNumericString();

  const payload = {
    amount: rawValue
  };

  fetch('/api/pay', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });
});

В этом варианте отправляется гарантированно нормализованное значение без форматирования.

Использование FormData и замена значений

При работе с FormData важно учитывать, что он читает DOM-значения напрямую. Поэтому требуется либо предварительная нормализация, либо замена значений перед отправкой.

document.querySelector('#paymentForm').addEventListener('submit', (e) => {
  e.preventDefault();

  const form = e.target;
  const formData = new FormData(form);

  const amount = AutoNumeric.getAutoNumericElement(
    document.querySelector('#amount')
  ).getNumericString();

  formData.set('amount', amount);

  fetch('/api/pay', {
    method: 'POST',
    body: formData
  });
});

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

Скрытые поля как стратегия разделения данных

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

<form id="paymentForm">
  <input id="amount_view">
  <input type="hidden" name="amount" id="amount_raw">
</form>
const view = document.querySelector('#amount_view');
const hidden = document.querySelector('#amount_raw');

const an = new AutoNumeric(view, {
  decimalCharacter: ',',
  digitGroupSeparator: ' ',
  currencySymbol: '€'
});

view.addEventListener('input', () => {
  hidden.value = an.getNumericString();
});

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

Автоматическая синхронизация при blur

Часто обновление скрытого поля выполняется не на каждом вводе, а при потере фокуса:

view.addEventListener('blur', () => {
  hidden.value = an.getNumericString();
});

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

Удаление форматирования перед отправкой

Некоторые сценарии требуют временного «разформатирования» input непосредственно перед сабмитом. AutoNumeric позволяет управлять этим через методы изменения режима отображения.

document.querySelector('#paymentForm').addEventListener('submit', (e) => {
  const an = AutoNumeric.getAutoNumericElement(document.querySelector('#amount'));

  an.unformat();

  // форма отправится уже с чистым значением
});

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

Восстановление формата после отправки

Если используется временное снятие форматирования, важно восстановить отображение:

document.querySelector('#paymentForm').addEventListener('submit', async (e) => {
  e.preventDefault();

  const el = document.querySelector('#amount');
  const an = AutoNumeric.getAutoNumericElement(el);

  an.unformat();

  const formData = new FormData(e.target);

  await fetch('/api/pay', {
    method: 'POST',
    body: formData
  });

  an.reformat();
});

Обработка нескольких полей формы

В реальных формах часто присутствует несколько числовых полей. Для них применяется единый проход по экземплярам AutoNumeric.

document.querySelector('#paymentForm').addEventListener('submit', (e) => {
  e.preventDefault();

  const data = {};
  const elements = document.querySelectorAll('input');

  elements.forEach((el) => {
    const an = AutoNumeric.getAutoNumericElement(el);

    if (an) {
      data[el.name] = an.getNumericString();
    } else {
      data[el.name] = el.value;
    }
  });

  fetch('/api/pay', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
});

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

Особенности сериализации при AJAX

При использовании XMLHttpRequest или fetch важно учитывать, что форматированные значения могут случайно попасть в payload, если не выполнена нормализация.

Основная стратегия заключается в том, чтобы никогда не полагаться на DOM-значение для числовых полей, а всегда обращаться к экземпляру AutoNumeric.

Валидация перед отправкой

Перед отправкой формы часто требуется дополнительная проверка:

const an = AutoNumeric.getAutoNumericElement(document.querySelector('#amount'));

const value = an.getNumber();

if (Number.isNaN(value) || value <= 0) {
  throw new Error('Invalid amount');
}

Использование getNumber() позволяет работать с типом Number, что упрощает арифметику и проверки диапазонов.

Обработка пустых значений

AutoNumeric различает пустое поле и нулевое значение. При отправке важно учитывать это различие:

const raw = an.getNumericString();

const normalized = raw === '' ? null : raw;

Это особенно важно для API, где null и 0 имеют разную семантику.

Итоговая модель поведения при сабмите

В типовой архитектуре обработки формы с AutoNumeric соблюдается следующая логика:

  • пользователь вводит форматированное значение
  • AutoNumeric поддерживает синхронизацию отображения
  • при сабмите извлекается чистое значение через API экземпляра
  • отправка выполняется через JSON или FormData
  • DOM-значение не используется как источник истины для чисел

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