В приложениях с большим количеством числовых полей часто возникает необходимость централизованно обрабатывать все экземпляры AutoNumeric: изменять настройки, получать значения, выполнять синхронизацию, массовое обновление интерфейса или очистку данных. Для решения таких задач библиотека предоставляет механизмы доступа к коллекциям экземпляров и инструменты обхода зарегистрированных объектов.
Итерация по экземплярам позволяет:
Каждый объект AutoNumeric представляет собой независимый экземпляр со своим состоянием, настройками и связанным DOM-элементом.
Пример создания нескольких экземпляров:
const price = new AutoNumeric('#price', {
currencySymbol: '$',
decimalPlaces: 2
});
const tax = new AutoNumeric('#tax', {
suffixText: '%',
decimalPlaces: 1
});
const quantity = new AutoNumeric('#quantity', {
decimalPlaces: 0
});
При большом количестве элементов хранение ссылок вручную становится неудобным. Обычно экземпляры объединяют в массивы или используют встроенные групповые механизмы библиотеки.
Самый простой способ организации итерации — хранение объектов в массиве.
const fields = [
new AutoNumeric('#price'),
new AutoNumeric('#discount'),
new AutoNumeric('#tax'),
new AutoNumeric('#total')
];
После этого становятся доступны любые стандартные методы перебора JavaScript.
forEachМетод forEach подходит для последовательной обработки
всех экземпляров.
fields.forEach(instance => {
instance.clear();
});
В данном случае очищаются все поля одновременно.
Пример установки одинакового значения:
fields.forEach(instance => {
instance.set(1000);
});
Частая задача — извлечение чисел из всех экземпляров.
const values = fields.map(instance => {
return instance.getNumber();
});
console.log(values);
Результат:
[1000, 250, 20, 1270]
Итерация часто используется для вычислений.
const total = fields.reduce((sum, instance) => {
return sum + Number(instance.getNumber());
}, 0);
console.log(total);
for...ofКонструкция for...of особенно удобна при сложной
логике.
for (const instance of fields) {
if (instance.getNumber() < 0) {
instance.node().classList.add('negative');
}
}
entries()Иногда требуется индекс элемента.
for (const [index, instance] of fields.entries()) {
console.log(index, instance.getFormatted());
}
AutoNumeric позволяет изменять конфигурацию после инициализации.
fields.forEach(instance => {
instance.update({
digitGroupSeparator: ' ',
decimalCharacter: ','
});
});
После выполнения все поля будут использовать одинаковые локализованные настройки.
fields.forEach(instance => {
instance.update({
currencySymbol: '€'
});
});
Часто применяется динамическое изменение параметров в зависимости от состояния интерфейса.
function switchToPercentageMode(instances) {
instances.forEach(instance => {
instance.update({
suffixText: '%',
decimalPlaces: 2
});
});
}
Каждый экземпляр связан с HTML-узлом.
fields.forEach(instance => {
const element = instance.node();
element.style.backgroundColor = '#f5f5f5';
});
Можно обрабатывать только определённые элементы.
const emptyFields = fields.filter(instance => {
return instance.getNumber() === null;
});
emptyFields.forEach(instance => {
instance.set(0);
});
В крупных приложениях удобно разделять поля по категориям.
const financeFields = [
new AutoNumeric('#salary'),
new AutoNumeric('#bonus'),
new AutoNumeric('#expenses')
];
const percentFields = [
new AutoNumeric('#tax'),
new AutoNumeric('#interest')
];
После этого можно применять разные сценарии обработки.
AutoNumeric часто создаётся динамически для группы элементов.
const elements = document.querySelectorAll('.numeric');
const instances = [];
elements.forEach(element => {
instances.push(new AutoNumeric(element));
});
mapБолее компактный вариант:
const instances = [...document.querySelectorAll('.numeric')]
.map(element => new AutoNumeric(element));
При динамическом добавлении элементов необходимо повторно создавать экземпляры.
function initializeNumericFields() {
return [...document.querySelectorAll('.numeric')]
.map(element => new AutoNumeric(element));
}
function applyData(instances, data) {
instances.forEach((instance, index) => {
instance.set(data[index]);
});
}
fields.forEach(instance => {
const value = instance.getNumber();
if (value > 1000000) {
console.warn('Превышен лимит');
}
});
const formattedValues = fields.map(instance => {
return instance.getFormatted();
});
Пример результата:
[
'$1,000.00',
'$250.00',
'$20.00'
]
const rawValues = fields.map(instance => {
return instance.rawValue;
});
При уничтожении компонентов полезно централизованно удалять экземпляры.
fields.forEach(instance => {
instance.remove();
});
После удаления:
Иногда данные загружаются с сервера.
async function updateFields(instances) {
const response = await fetch('/api/prices');
const data = await response.json();
instances.forEach((instance, index) => {
instance.set(data[index]);
});
}
function syncFields(source, targets) {
source.node().addEventListener('autoNumeric:rawValueModified', () => {
const value = source.getNumber();
targets.forEach(instance => {
instance.set(value);
});
});
}
Сбор значений формы:
function collectFormData(instances) {
const result = {};
instances.forEach(instance => {
const name = instance.node().name;
result[name] = instance.getNumber();
});
return result;
}
everyПроверка всех значений:
const allPositive = fields.every(instance => {
return instance.getNumber() >= 0;
});
someПроверка наличия отрицательных значений:
const hasNegative = fields.some(instance => {
return instance.getNumber() < 0;
});
fields.sort((a, b) => {
return a.getNumber() - b.getNumber();
});
fields.forEach(instance => {
try {
console.log(instance.getNumber());
} catch(error) {
console.error(error);
}
});
AutoNumeric особенно часто используется в табличных интерфейсах.
const rows = [...document.querySelectorAll('.row-price')];
const priceInstances = rows.map(row => {
return new AutoNumeric(row);
});
fields.forEach(instance => {
instance.node().disabled = true;
});
fields.forEach(instance => {
instance.node().disabled = false;
});
fields.forEach(instance => {
instance.node().classList.toggle('highlight');
});
В сложных приложениях экземпляры могут храниться в
WeakMap.
const storage = new WeakMap();
document.querySelectorAll('.numeric').forEach(element => {
const instance = new AutoNumeric(element);
storage.set(element, instance);
});
Получение экземпляра:
const instance = storage.get(element);
Если экземпляры организованы как объект:
const instances = {
salary: new AutoNumeric('#salary'),
bonus: new AutoNumeric('#bonus'),
tax: new AutoNumeric('#tax')
};
Перебор:
Object.values(instances).forEach(instance => {
instance.clear();
});
Object.entries(instances).forEach(([name, instance]) => {
console.log(name, instance.getFormatted());
});
function forEachInstance(instances, callback) {
instances.forEach(instance => {
callback(instance);
});
}
Использование:
forEachInstance(fields, instance => {
instance.set(0);
});
fields.forEach(instance => {
instance.update({
digitGroupSeparator: '.',
decimalCharacter: ',',
currencySymbol: '₸'
});
});
function applyDarkTheme(instances) {
instances.forEach(instance => {
instance.node().classList.add('dark-input');
});
}
fields.forEach(instance => {
const value = instance.getNumber();
if (value < 0 || value > 10000) {
instance.node().classList.add('invalid');
}
});
При работе с сотнями экземпляров важно учитывать производительность.
Проблемы:
update;Оптимизация:
requestAnimationFrame(() => {
fields.forEach(instance => {
instance.set(100);
});
});
function processInChunks(instances, size = 50) {
for (let i = 0; i < instances.length; i += size) {
const chunk = instances.slice(i, i + size);
chunk.forEach(instance => {
instance.clear();
});
}
}
const instanceSet = new Set();
instanceSet.add(new AutoNumeric('#a'));
instanceSet.add(new AutoNumeric('#b'));
for (const instance of instanceSet) {
instance.set(1);
}
function copyValues(sourceGroup, targetGroup) {
sourceGroup.forEach((instance, index) => {
targetGroup[index].set(
instance.getNumber()
);
});
}
Пример простого менеджера:
class NumericManager {
constructor() {
this.instances = [];
}
register(instance) {
this.instances.push(instance);
}
clearAll() {
this.instances.forEach(instance => {
instance.clear();
});
}
disableAll() {
this.instances.forEach(instance => {
instance.node().disabled = true;
});
}
enableAll() {
this.instances.forEach(instance => {
instance.node().disabled = false;
});
}
destroyAll() {
this.instances.forEach(instance => {
instance.remove();
});
this.instances = [];
}
}
Использование:
const manager = new NumericManager();
manager.register(new AutoNumeric('#price'));
manager.register(new AutoNumeric('#tax'));
manager.clearAll();