Los formularios y controles, como <input>, tienen muchos eventos y propiedades especiales.
Trabajar con formularios será mucho más conveniente cuando los aprendamos.
Navegación: Formularios y elementos
Los formularios del documento son miembros de la colección especial document.forms.
Esa es la llamada “Colección nombrada”: es ambas cosas, nombrada y ordenada. Podemos usar el nombre o el número en el documento para conseguir el formulario.
document.forms.my; // el formulario con name="my"
document.forms[0]; // el primer formulario en el documento
Cuando tenemos un formulario, cualquier elemento se encuentra disponible en la colección nombrada form.elements.
Por ejemplo:
<form name="my">
<input name="one" value="1">
<input name="two" value="2">
</form>
<script>
// obtención del formulario
let form = document.forms.my; // elemento <form name="my">
// get the element
let elem = form.elements.one; // elemento <input name="one">
alert(elem.value); // 1
</script>
Puede haber múltiples elementos con el mismo nombre. Esto es típico en el caso de los botones de radio y checkboxes.
En ese caso form.elements[name] es una colección. Por ejemplo:
<form>
<input type="radio" name="age" value="10">
<input type="radio" name="age" value="20">
</form>
<script>
let form = document.forms[0];
let ageElems = form.elements.age;
alert(ageElems[0]); // [object HTMLInputElement]
</script>
Estas propiedades de navegación no dependen de la estructura de las etiquetas. Todos los controles, sin importar qué tan profundos se encuentren en el formulario, están disponibles en form.elements.
Un formulario puede tener uno o varios elementos <fieldset> dentro. Estos también tienen la propiedad elements que lista los controles del formulario dentro de ellos.
Por ejemplo:
<body>
<form id="form">
<fieldset name="userFields">
<legend>info</legend>
<input name="login" type="text">
</fieldset>
</form>
<script>
alert(form.elements.login); // <input name="login">
let fieldset = form.elements.userFields;
alert(fieldset); // HTMLFieldSetElement
// podemos obtener el input por su nombre tanto desde el formulario como desde el fieldset
alert(fieldset.elements.login == form.elements.login); // true
</script>
</body>
form.nameHay una notación corta: podemos acceder el elemento como form[index/name].
En otras palabras, en lugar de form.elements.login podemos escribir form.login.
Esto también funciona, pero tiene un error menor: si accedemos un elemento, y cambiamos su name, se mantendrá disponible mediante el nombre anterior (así como mediante el nuevo).
Esto es fácil de ver en un ejemplo:
<form id="form">
<input name="login">
</form>
<script>
alert(form.elements.login == form.login); // true, el mismo <input>
form.login.name = "username"; // cambiamos el nombre el <input>
// form.elements actualiza el nombre:
alert(form.elements.login); // undefined
alert(form.elements.username); // input
// form permite ambos nombres: el nuevo y el viejo
alert(form.username == form.login); // true
</script>
Esto usualmente no es un problema, porque raramente se cambian los nombres de los elementos de un formulario.
Referencia inversa: element.form
Para cualquier elemento, el formulario está disponible como element.form. Así que un formulario referencia todos los elementos, y los elementos referencian el formulario.
Aquí la imagen:
Por ejemplo:
<form id="form">
<input type="text" name="login">
</form>
<script>
// form -> element
let login = form.login;
// element -> form
alert(login.form); // HTMLFormElement
</script>
Elementos del formulario
Hablemos de los controles de los formularios.
input y textarea
Podemos acceder sus valores como input.value (cadena) o input.checked (booleano) para casillas de verificación (checkboxes) y botones de opción (radio buttons).
De esta manera:
input.value = "New value";
textarea.value = "New text";
input.checked = true; // para checkboxes o radios
textarea.value, no textarea.innerHTMLObserva que incluso aunque <textarea>...</textarea> contenga su valor como HTML anidado, nunca deberíamos usar textarea.innerHTML para acceder a él.
Esto solo guarda el HTML que había inicialmente en la página, no su valor actual.
select y option
Un elemento <select> tiene 3 propiedades importantes:
select.options– la colección de subelementos<option>,select.value– el valor del<option>seleccionado actualmente, yselect.selectedIndex– el número del<option>seleccionado actualmente.
Ellas proveen tres formas diferentes de asignar un valor para un elemento <select>:
- Encontrar el elemento
<option>correspondiente (por ejemplo entreselect.options) y asignar a suoption.selecteduntrue. - Si conocemos un nuevo valor: Asignar tal valor a
select.value. - Si conocemos el nuevo número de opción: Asignar tal número a
select.selectedIndex.
Aquí hay un ejemplo de los tres métodos:
<select id="select">
<option value="apple">Apple</option>
<option value="pear">Pear</option>
<option value="banana">Banana</option>
</select>
<script>
// las tres líneas hacen lo mismo
select.options[2].selected = true;
select.selectedIndex = 2;
select.value = 'banana';
// Recuerda que las opciones comienzan en cero, así que index 2 significa la tercera opción.
</script>
A diferencia de la mayoría de controles, <select> permite seleccionar múltiples opciones a la vez si tiene el atributo multiple. Esta característica es raramente utilizada.
En ese caso, necesitamos usar la primera forma: Añade/elimina la propiedad selected de los subelementos <option>.
Podemos obtener su colección como select.options, por ejemplo:
<select id="select" multiple>
<option value="blues" selected>Blues</option>
<option value="rock" selected>Rock</option>
<option value="classic">Classic</option>
</select>
<script>
// obtener todos los valores seleccionados del multi-select
let selected = Array.from(select.options)
.filter(option => option.selected)
.map(option => option.value);
alert(selected); // blues,rock
</script>
La especificación completa del elemento <select> está disponible en la especificación https://html.spec.whatwg.org/multipage/forms.html#the-select-element.
new Option
En la especificación hay una sintaxis muy corta para crear elementos <option>:
option = new Option(text, value, defaultSelected, selected);
Esta sintaxis es opcional. Podemos usar document.createElement('option') y asignar atributos manualmente. Aún puede ser más corta, aquí los parámetros:
text– el texto dentro del option,value– el valor del option,defaultSelected– si estrue, entonces se le crea el atributo HTMLselected,selected– si estrue, el option se selecciona.
La diferencia entre defaultSelected y selected es que defaultSelected define si el atributo HTML (el que obtenemos con option.getAttribute('selected')), mientras que selected define si el option está seleccionado o no en el DOM.
En la práctica, uno debería usualmente establecer ambos valores en true o false. O simplemente omitirlos, quedarán con el predeterminado false.
Por ejemplo, aquí creamos un nuevo Option “unselected”:
let option = new Option("Text", "value");
// crea <option value="value">Text</option>
El mismo elemento, pero seleccionado:
let option = new Option("Text", "value", true, true);
Los elementos Option tienen propiedades:
option.selected- Es el option seleccionado.
option.index- El número del option respecto a los demás en su
<select>. option.text- El contenido del option (visto por el visitante).
Referencias
- Especificación: https://html.spec.whatwg.org/multipage/forms.html.
Resumen
Navegación de formularios:
document.forms- Un formulario está disponible como
document.forms[name/index]. form.elements- Los elementos del formulario están disponibles como
form.elements[name/index], o puedes usar soloform[name/index]. La propiedadelementstambién funciona para los<fieldset>. element.form- Los elementos referencian a su formulario en la propiedad
form.
El valor está disponible con input.value, textarea.value, select.value etc. Para checkboxes y radios, usa input.checked para determinar si el valor está seleccionado.
Para <select> también podemos obtener el valor con el índice select.selectedIndex o a través de la colección de opciones select.options.
Esto es lo básico para empezar a trabajar con formularios. Conoceremos muchos ejemplos más adelante en el tutorial.
En el siguiente capítulo vamos a hablar sobre los eventos focus y blur que pueden ocurrir en cualquier elemento, pero son manejados mayormente en formularios.
Comentarios
<code>, para varias líneas – envolverlas en la etiqueta<pre>, para más de 10 líneas – utilice una entorno controlado (sandbox) (plnkr, jsbin, codepen…)