Работа с несколькими числовыми полями в одной форме в AutoNumeric требует понимания того, что каждая инстанция библиотеки существует независимо, но при этом все они обычно участвуют в едином процессе сбора и валидации данных формы. Основная сложность заключается не в самой инициализации форматирования, а в согласованной работе с DOM-состоянием, извлечении «чистых» значений и управлении динамическими полями.
Каждое поле ввода, к которому применяется AutoNumeric, превращается в отдельный объект-обёртку с собственными настройками форматирования, локализации и состояния курсора. При работе с формой это означает:
input.valueПри инициализации нескольких полей создаётся набор независимых экземпляров:
const amount = new AutoNumeric('#amount', {
digitGroupSeparator: ' ',
decimalCharacter: ',',
decimalPlaces: 2
});
const tax = new AutoNumeric('#tax', {
digitGroupSeparator: ' ',
decimalCharacter: ',',
decimalPlaces: 2
});
const discount = new AutoNumeric('#discount', {
digitGroupSeparator: ' ',
decimalCharacter: ',',
decimalPlaces: 2
});
Каждый экземпляр изолирован, но в контексте формы они начинают взаимодействовать косвенно — через вычисления, события и сбор данных.
При большом количестве полей ручное создание экземпляров становится неэффективным. Типичный подход — делегирование инициализации через атрибуты:
<form id="invoiceForm">
<input id="amount" data-an />
<input id="tax" data-an />
<input id="discount" data-an />
<input id="total" data-an-readonly />
</form>
Инициализация всех полей одной операцией:
const elements = document.querySelectorAll('[data-an], [data-an-readonly]');
const instances = [];
elements.forEach((el) => {
const isReadonly = el.hasAttribute('data-an-readonly');
const instance = new AutoNumeric(el, {
decimalCharacter: ',',
digitGroupSeparator: ' ',
decimalPlaces: 2,
readOnly: isReadonly
});
instances.push(instance);
});
Такой подход создаёт централизованный список инстансов, что критично для дальнейшей синхронизации и массового извлечения данных.
Ключевой момент при работе с множественными полями — отказ от
использования FormData как единственного источника числовых
значений. AutoNumeric хранит отформатированное значение в DOM, поэтому
прямое чтение value приводит к ошибкам.
Правильный подход — извлечение числовых значений через API:
const formData = {};
instances.forEach((instance) => {
const el = instance.domElement;
const name = el.id || el.name;
formData[name] = instance.getNumber();
});
Метод getNumber() возвращает нормализованное значение
без разделителей групп и с учётом настроек точности.
Для сериализации перед отправкой:
const payload = JSON.stringify(formData);
В формах часто присутствуют зависимые поля: налог, скидка, итоговая сумма. В таких сценариях AutoNumeric используется не только как форматтер, но и как инструмент UI-слоя для реактивных вычислений.
Пример зависимости:
amount — базовая суммаtax — процент налогаdiscount — скидкаtotal — вычисляемый результатfunction recalculate() {
const amountVal = amount.getNumber();
const taxVal = tax.getNumber();
const discountVal = discount.getNumber();
const totalValue = amountVal + (amountVal * taxVal / 100) - discountVal;
total.set(totalValue);
}
Здесь важно, что метод set() принимает числовое
значение, а AutoNumeric сам приводит его к нужному формату
отображения.
При множественных инстансах критично централизовать обработку событий. Используется один обработчик, привязанный к каждому экземпляру:
instances.forEach((instance) => {
instance.domElement.addEventListener('autoNumeric:formatted', recalculate);
instance.domElement.addEventListener('input', recalculate);
});
Событие autoNumeric:formatted позволяет реагировать уже
на завершённое форматирование, что уменьшает количество промежуточных
пересчётов.
В более сложных формах применяется throttling:
let timeout;
function throttledRecalculate() {
clearTimeout(timeout);
timeout = setTimeout(recalculate, 50);
}
Формы часто позволяют добавлять строки (например, позиции счёта). В этом случае каждый новый input требует отдельной инициализации AutoNumeric.
function addRow() {
const container = document.querySelector('#items');
const input = document.createElement('input');
input.type = 'text';
input.className = 'price';
container.appendChild(input);
const instance = new AutoNumeric(input, {
decimalCharacter: ',',
digitGroupSeparator: ' ',
decimalPlaces: 2
});
instances.push(instance);
}
Важно поддерживать актуальный массив instances, иначе
сбор данных формы станет неконсистентным.
При удалении строк необходимо корректно освобождать ресурсы:
function removeRow(index) {
const instance = instances[index];
instance.remove(); // или destroy в зависимости от версии
instances.splice(index, 1);
}
Игнорирование удаления приводит к накоплению «мертвых» ссылок и некорректной работе пересчётов.
Одним из ключевых аспектов при работе с несколькими полями является строгая граница между UI и данными:
getNumber()Пример неправильного подхода:
const value = document.querySelector('#amount').value;
Этот вариант возвращает форматированную строку, непригодную для вычислений.
Корректный вариант:
const value = amount.getNumber();
В некоторых сценариях требуется обновить сразу несколько полей (например, смена валюты или коэффициента пересчёта):
function applyMultiplier(multiplier) {
instances.forEach((instance) => {
const value = instance.getNumber();
instance.set(value * multiplier);
});
}
AutoNumeric автоматически перерисовывает отображение при каждом
set(), сохраняя формат.
При наличии множества полей возникает задача контроля валидности всей формы:
function isFormValid() {
return instances.every((instance) => {
const value = instance.getNumber();
return value !== null && !isNaN(value);
});
}
Дополнительно можно учитывать ограничения конфигурации:
При сотнях инстансов важны следующие принципы:
Пример пакетного обновления:
function batchUpdate(updates) {
updates.forEach(({ instance, value }) => {
instance.set(value);
});
}
После завершения всех операций выполняется один пересчёт зависимых значений.
В одной форме все поля должны использовать одинаковую локализацию, иначе визуальное восприятие данных становится несогласованным:
const commonOptions = {
digitGroupSeparator: ' ',
decimalCharacter: ',',
decimalPlaces: 2
};
instances.forEach((instance) => {
instance.update(commonOptions);
});
Изменение локали «на лету» требует обновления всех инстансов, иначе пользовательский ввод становится неоднородным.
Перед отправкой формы важно гарантировать, что данные извлекаются из всех инстансов:
form.addEventListener('submit', (e) => {
e.preventDefault();
const result = instances.reduce((acc, instance) => {
const key = instance.domElement.name;
acc[key] = instance.getNumber();
return acc;
}, {});
send(result);
});
В этом сценарии AutoNumeric полностью заменяет стандартную модель чтения значений формы, обеспечивая единообразие данных независимо от форматирования на экране.