I forms e gli elementi control, come <input>
hanno una serie di eventi e proprietà peculiari.
Lavorando con i forms, questi saranno molto comodi quando li avremo imparati.
Navigazione: form e elements
I form del documento sono membri della speciale collezione document.forms
.
Questa è una cosiddetta “named collection”: è sia associativa che ordinata. Possiamo usare sia il nome che l’indice nel documento per accedervi.
document.forms.my - il form con name="my"
document.forms[0] - il primo form del documento
Quando abbiamo un form, allora tutti gli elementi saranno contenuti nella named collection form.elements
.
Per esempio:
<form name="my">
<input name="one" value="1">
<input name="two" value="2">
</form>
<script>
// ottiene il form
let form = document.forms.my; // <form name="my"> element
// ottiene l'elemento
let elem = form.elements.one; // <input name="one"> element
alert(elem.value); // 1
</script>
Potrebbero esserci elementi multipli con lo stesso nome, ed è una cosa che capita spesso con i radio buttons ed i checkbox.
In questo caso form.elements[name]
sarà una collection, per esempio:
<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>
Queste proprietà di navigazione non dipendono dalla struttura dei tags. Ogni control element, è irrilevante quanto in profondità sia dentro il form, sarà contenuto ed accessibile da form.elements
.
Un form può avere uno o più elementi <fieldset>
all’interno. Questi hanno anche proprietà elements
che mostrano dei form controls all’interno.
Per esempio:
<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
// possiamo ottenere l'input sia dal nome del form sia dal fieldset
alert(fieldset.elements.login == form.elements.login); // true
</script>
</body>
form.name
Esiste una notazione breve: possiamo accedere all’elemento come form[index/name]
.
In altre parole, invece di form.elements.login
possiamo scrivere form.login
.
Funziona ugualmente, ma c’è un piccolo problema: se accediamo a un elemento, che in successivamente cambia il suo name
, questo sarà ancora accessibile sia attraverso il vecchio nome, ma anche tramite quello nuovo.
È facile capirlo da un esempio:
<form id="form">
<input name="login">
</form>
<script>
alert(form.elements.login == form.login); // true, lo stesso <input>
form.login.name = "username"; // cambio del nome dell'input
// form.elements ha aggiornato il nome:
alert(form.elements.login); // undefined
alert(form.elements.username); // input
// form permette entrambi i nomi: sia quello nuovo che quello vecchio
alert(form.username == form.login); // true
</script>
Solitamente non è un problema, in quanto raramente andiamo a modificare il nome degli elementi dei form.
Backreference: element.form
Per ogni elemento, il form è disponibile come element.form
. Quindi un form referenzia tutti gli elementi, e gli elementi referenziano il form.
Come possiamo vedere in figura:
Per esempio:
<form id="form">
<input type="text" name="login">
</form>
<script>
// form -> element
let login = form.login;
// element -> form
alert(login.form); // HTMLFormElement
</script>
Elementi del form
Parliamo un po’ dei form controls.
input e textarea
Possiamo accedere ai lori valori tramite input.value
(string) o input.checked
(boolean) per i checkbox.
Come in questo caso:
input.value = "Nuovo valore";
textarea.value = "Nuovo testo";
input.checked = true; // per una checkbox o un radio button
textarea.value
, e non textarea.innerHTML
Nota bene che, nonostante anche <textarea>...</textarea>
contenga il suo valore come HTML annidato, non dovremmo mai usare textarea.innerHTML
per accedervi.
Esso conterrà solamente l’HTML che era stato inizialmente impostato nella pagina, e non il valore attuale.
select ed option
Un elemento <select>
contiene 3 importanti proprietà:
select.options
– la collezione di sottoelementi<option>
,select.value
– il valore di<option>
attualmente selezionato,select.selectedIndex
– l’indice di<option>
attualmente selezionato.
Forniscono tre modi differenti per impostare un valore per un <select>
:
- Trova il corrispondente elemento
<option>
(ad esempio tra iselect.options
) ed imposta il suooption.selected
atrue
. - Se conosciamo il nuovo valore: imposta
select.value
al nuovo valore. - Se conosciamo l’indice della nuova opzione: imposta
select.selectedIndex
su quell’indice.
Ecco un esempio per tutti e tre i metodi:
<select id="select">
<option value="apple">Mela</option>
<option value="pear">Pera</option>
<option value="banana">Banana</option>
</select>
<script>
// tutte e tre le righe di codice fanno la stessa cosa
select.options[2].selected = true;
select.selectedIndex = 2;
select.value = 'banana';
// nota bene: le options cominciano da indice zero, quindi indice 2 significa la option numero 3.
</script>
Diversamente da altri controls, <select>
permette di selezionare più opzioni alla volta se contiene l’attributo multiple
. Comunque questo attributo viene usato raramente.
Per valori multipli selezionati, usiamo il primo modo per impostare i valori: aggiungere/rimuovere la proprietà selected
dai sottoelementi <option>
.
Ecco un esempio di come ottenere i valori selezionati da un multi-select:
<select id="select" multiple>
<option value="blues" selected>Blues</option>
<option value="rock" selected>Rock</option>
<option value="classic">Classic</option>
</select>
<script>
// ottiene tutti i valori selezionati dal multi-select
let selected = Array.from(select.options)
.filter(option => option.selected)
.map(option => option.value);
alert(selected); // blues,rock
</script>
Le specifiche complete dell’elemento <select>
sono disponibili nelle specifiche https://html.spec.whatwg.org/multipage/forms.html#the-select-element.
new Option
Nelle specifiche specification viene descritta una sintassi breve ed elegante per creare una elemento <option>
:
option = new Option(text, value, defaultSelected, selected);
Questa sintassi è opzionale. Possiamo usare document.createElement('option')
ed impostare gli attributi manualmente. Tuttavia, potrebbe essere breve, quindi ecco i parametri:
text
– il testo dentro option,value
– il valore di option,defaultSelected
– setrue
, allora verrà creato l’attributo HTMLselected
,selected
– setrue
, allora l’opzione verrà selezionata.
La differenza tra defaultSelected
e selected
è che defaultSelected
imposta l’attributo HTML (che possiamo ottenere usando option.getAttribute('selected')
, mentre selected
definisce lo stato della selezione (se è selezionata o meno).
In pratica, solitamente possiamo impostare entrambi i valori a true
o false
(oppure ometterli, che equivale a false
).
Per esempio, ecco un nuovo elemento option “non selezionato”:
let option = new Option("Testo", "value");
// crea <option value="value">Testo</option>
La stesso elemento option, ma stavolta selezionato:
let option = new Option("Testo", "value", true, true);
Gli elementi option hanno delle proprietà:
option.selected
- Se l’opzione è selezionata.
option.index
- L’indice dell’opzione in mezzo agli altri elementi option del suo elemento
<select>
. option.text
- Il contenuto testuale dell’elemento option (visto dall’utente).
Riferimenti
- Specification: https://html.spec.whatwg.org/multipage/forms.html.
Riepilogo
Navigazione dei form:
document.forms
- Un form è disponibile come
document.forms[name/index]
. form.elements
- Gli elementi del form sono disponibili come
form.elements[name/index]
, oppure, più semplicemente conform[name/index]
. La proprietàelements
esiste anche per i<fieldset>
. element.form
- Gli elementi referenziano i loro form nella proprietà
form
.
Il valore è disponibile come input.value
, textarea.value
, select.value
etc. Oppure come input.checked
per determinare la selezione per checkbox e radio buttons.
Per <select>
possiamo anche ottenere il valore tramite l’indice select.selectedIndex
o attraverso la collezione di options select.options
.
Queste sono le basi da cui partire con i form. Incontreremo molti esempi più avanti nel tutorial.
Nel prossimo capitolo affronteremo gli eventi focus
e blur
che possono avvenire per qualunque evento, ma sono maggiormente gestiti nei form.
Commenti
<code>
, per molte righe – includile nel tag<pre>
, per più di 10 righe – utilizza una sandbox (plnkr, jsbin, codepen…)