Элементы формы и их значения
Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.
Поле формы — коробка, в которую пишет пользователь, а не вы. Поэтому у него всегда два значения: value в разметке — то, с чего всё началось, и свойство value в JavaScript — то, что там прямо сейчас.
У форм есть свой короткий путь: document.forms — коллекция всех форм страницы, и обращаться к ней можно по name или id. Внутри формы такая же коллекция полей — form.elements: по имени, по индексу, с обычным length.
Это удобнее, чем querySelector: имена полей вы всё равно пишете в разметке ради отправки на сервер, так что второго набора селекторов не требуется.
В form.elements лежат все управляющие элементы формы. А в отправку попадают только те, у которых есть name и которые не выключены через disabled. Проверить состав отправки можно объектом FormData.
У input и textarea текущее содержимое читается одинаково — через value. Для textarea это важно отдельно: текст между тегами — только начальное значение, и innerHTML после правок пользователя покажет старое. Начальное значение доступно как defaultValue.
Атрибут в разметке — стартовое значение, свойство — текущее. Пользователь печатает в свойство, поэтому getAttribute("value") останется прежним, а input.value скажет правду. Обратное тоже верно: setAttribute("value", ...) после первого ввода уже ничего не изменит на экране.
И главная ловушка: value — строка. Даже у type="number". Числовой вид лежит рядом, в valueAsNumber (для type="date" есть valueAsDate).
У флажка и переключателя value тоже есть, но оно отвечает на другой вопрос: «какую строку отправить, если элемент отмечен». Само состояние — булево свойство checked, а начальное состояние из разметки — defaultChecked.
Радиокнопки с одинаковым name внутри формы собираются в RadioNodeList. У неё есть своё value — значение отмеченного элемента; записав туда строку, вы отметите нужный переключатель.
Если атрибут value не задан, браузер подставляет строку on — историческое значение по умолчанию. Оно ничего не говорит о состоянии: у снятого флажка value тоже on.
У select три способа спросить об одном и том же: value — значение выбранной опции, selectedIndex — её номер, options — коллекция всех option. Запись в value выбирает опцию с таким значением, запись в selectedIndex — по номеру.
Со списком, где разрешено несколько значений (multiple), value становится бесполезным: оно вернёт только первую выбранную опцию. Все отмеченные лежат в selectedOptions. Новую опцию удобно создавать конструктором new Option(текст, значение) и добавлять обычным append.
| Элемент | Что читать | Заметка |
|---|---|---|
| input type="text" | value | всегда строка |
| textarea | value | не innerHTML |
| input type="checkbox" | checked | value — строка для отправки |
| группа radio | form.elements.name.value | значение отмеченного |
| select | value, selectedIndex | для multiple — selectedOptions |
Связь двусторонняя: из формы видны поля, а у каждого поля есть свойство form — ссылка на его форму. Причём элемент необязательно лежит внутри тега form: атрибут form="id-формы" присоединяет к ней поле из любого места страницы.
Практическая польза — обработчики. Из события известен элемент, из элемента — форма, из формы — все соседние поля. Не нужно ни глобальных переменных, ни поиска по документу.
- К форме и её полям есть короткий путь по именам: document.forms.имя, затем form.elements.имя. Работает и по id, и по индексу.
- value — всегда строка и всегда текущее значение. Начальное значение из разметки лежит отдельно, в defaultValue; для чисел есть valueAsNumber.
- У чекбокса и радио состояние — это checked, а value лишь строка для отправки (по умолчанию on). Значение отмеченного переключателя даёт form.elements.имя.value.
- У select читают value, selectedIndex и options; для multiple единственный честный источник — selectedOptions.
- Свойство element.form ведёт от поля обратно к форме — даже если поле лежит вне тега form и присоединено атрибутом form="id".
1/3В разметке было <input id="nick" value="rico">. Выполнили input.value = "neo". Что вернёт input.getAttribute("value")?
2/3В форме два радио с name="plan" и значениями free и pro, отмечен pro. Что вернёт form.elements.plan.value?
3/3У <select multiple> три опции, выбраны первая и третья. Что даст select.value?
Сводка по форме
Напишите функцию summary(form), которая собирает строку вида nick=rico;subscribe=true;level=pro: имя поля, знак равенства, значение. Для чекбокса значением считается true или false, для остальных — value. Порядок — как в разметке.
Коллекция form.elements перебирается как массив, а тип элемента подсказывает свойство type: у чекбокса это checkbox, у выпадающего списка — select-one.
Обратите внимание: у чекбокса намеренно берётся checked, а не value — иначе для снятого флажка вышло бы subscribe=on. Если бы в форме встретились поля без name, их стоило бы отфильтровать: .filter((el) => el.name).
Переключатель «выбрать все»
В форме четыре чекбокса: master и три обычных. Сделайте так, чтобы переключение master выставляло всем остальным то же состояние. Сам master в цикле пропускают: остальным присваивают его состояние, а ему самому присваивать уже нечего.
Событие change у чекбокса срабатывает и при программном click(), так что проверить решение можно без участия пользователя.
Второй клик снимает всё, включая ранее отмеченный b: обработчик копирует состояние мастера, а не переключает каждый флажок по отдельности.