Форматирование и внешние поля формы
Модуль обновляет два существующих hidden-input вне контейнера и форматированный output. Кнопка показывает FormData локально: запрос на сервер не отправляется.
HTML
<form id="range-form" class="range-demo">
<div id="range-budget-label" class="range-demo-label">Бюджет проекта</div>
<div id="range-budget" role="group" aria-labelledby="range-budget-label"></div>
<input type="hidden" id="range-budget-from" name="budget_from">
<input type="hidden" id="range-budget-to" name="budget_to">
<output id="range-budget-value" class="range-demo-result" aria-live="polite"></output>
<div class="range-demo-actions">
<button type="submit" class="btn btn-primary btn-sm">Показать FormData</button>
<button id="range-budget-reset" type="button" class="btn btn-surface btn-sm">Сбросить диапазон</button>
</div>
<pre id="range-form-result" class="range-demo-result" aria-live="polite">Нажмите «Показать FormData». Запрос на сервер не отправляется.</pre>
</form>
JavaScript
/**
* Описание: рабочий пример VGRangeSlider — form.
* Возможности: форматирование валюты, внешние hidden-поля и локальный просмотр FormData.
*/
import { VGRangeSlider } from 'vgapp';
function initRangeDemo() {
const root = document.querySelector('#range-budget');
if (!root || VGRangeSlider.getInstance(root)) return;
const formatter = new Intl.NumberFormat('ru-RU', {
style: 'currency', currency: 'RUB', maximumFractionDigits: 0
});
const slider = VGRangeSlider.init(root, {
range: true, min: 0, max: 100000, step: 1000, start: [20000, 80000],
input: { min: '#range-budget-from', max: '#range-budget-to' },
output: '#range-budget-value',
formatValue: value => formatter.format(value)
});
root.querySelector('.vg-range-slider__input--from').setAttribute('aria-label', 'Минимальный бюджет');
root.querySelector('.vg-range-slider__input--to').setAttribute('aria-label', 'Максимальный бюджет');
document.querySelector('#range-form').addEventListener('submit', (event) => {
event.preventDefault();
const values = Object.fromEntries(new FormData(event.currentTarget));
document.querySelector('#range-form-result').textContent = JSON.stringify(values, null, 2);
});
document.querySelector('#range-budget-reset').addEventListener('click', () => slider.setValue([20000, 80000]));
}
initRangeDemo();
CSS
/* Композиция демо; трек, ручки, шкала и подсказки оформляются VGRangeSlider. */
.range-demo {
min-width: 0;
padding: 1rem;
}
.range-demo-label {
display: block;
margin-bottom: 2.5rem;
font-weight: 600;
}
.range-demo-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: .75rem;
margin-top: 2rem;
}
.range-demo-result {
display: block;
margin: 1.5rem 0 0;
padding: .75rem;
border: 1px solid var(--vg-border-default);
border-radius: .5rem;
color: var(--vg-text-primary);
background: var(--vg-background-secondary);
overflow-wrap: anywhere;
white-space: pre-wrap;
}
.range-demo-log {
max-height: 15rem;
overflow-y: auto;
}