El abc de los formularios

Introducción

Entre las preguntas que se hacen en los forosdelweb, muchas se deben a dudas sobre formularios, y aunque la mayoría de ellas son de relativamente fácil resolución, seguramente sea interesante hacer un tutorial sobre estos elementos tan útiles.

La parte funcional de los formularios viene condicionada por la etiqueta form y sus atributos; y unos pocos controles (etiquetas de entrada, de selección o chequeo y botones) con una sencilla estructura de muy fácil comprensión.

Etiqueta form: Raíz del formulario

Una etiqueta form debe (o debería) tener definidos algunos atributos con importante información para su procesamiento: el atributo method (método) cuyos valores son get o post que indica cómo serán enviados los datos; una sencilla interpretación del método get es el envío de datos "por URL", o sea que son visibles en la línea de dirección del navegador.

Otro importante atributo es action (acción) que indica cuál será el destino del formulario; normalmente será una dirección web del tipo http://www.dominio_destino.extensión/pagina_procesadora... aunque el protocolo podría ser mailto:e-mail_destino... o incluso un script javascript:

Siguiendo con atributos importantes, enctype (tipo de envío) tiene como función, indicar de que tipo son los datos que se envían. Por ejemplo con el método get solo puede enviarse texto plano "text/plain", pero si se quisiera adjuntar algún archivo, debería ser multipart/form-data... para cualquier otra situación debería ser application/x-www-form-urlencoded

El atributo target indica la ventana (objeto window) de destino del formulario; si no se declara, la ventana destino será "_self" o sea la misma ventana (no confundir con action que es url de destino)

El resto de atributos no influyen en la funcionalidad del formulario, por lo que no describiremos aunque tanto id como name son atributos importantes para la referenciación con javascript.

Controles

Podemos clasificar los controles como de entrada de texto, selección, botones y datos ocultos. Todos los controles con información que se quiera enviar deben tener definido el atributo name (nombre) y el atributo value (valor), con la excepción de los controles que tengan etiqueta de cierre, cuyo value es su propio contenido (textarea/button) y los controles select, cuyo valor (value) se corresponde con la(s) opcion(es) que se encuentren seleccionadas; también pueden ser de sólo lectura (readonly), o estar deshabilitado/habilitado (disabled), chequeados (checked) o seleccionados (selected); también pueden tener una tecla de acceso asociada (atributo accesskey) y un orden de tabulación (atributo tabindex). Mostraremos las distintas posibilidades para cado uno de estos controles.

Entrada de datos simple (input type="text")

Para hablar de la etiqueta input, es difícil darle un significado, porque tiene la funcionalidad condicionada por el tipo (atributo type). Aunque como entrada se puede decir que debe tener el tipo text.

Entrada de texto con saltos de línea (textarea)

La etiqueta textarea crea un recuadro de texto con posibilidad de introducir varias líneas, y bastante más extenso que el caso anterior (en teoría ilimitado), tienen 2 atributos adicionales que indican el número de filas y columnas visibles. Otra peculiaridad es que no se define el atributo value, ya que el contenido de las etiquetas es ese valor.

Selección (simple y múltiple)

La etiqueta select se complementa con las opciones a seleccionar (etiquetas option). Como todas los controles de un formulario el atributo que le da el nombre es name, pero no tiene atributo value, porque ese atributo varía según el elemento option que esté seleccionado. Un atributo que sirve para poder seleccionar más de una opción es multiple; si se define indica que se pueden selecionar más de un elemento.

Radios y checkboxes (otra forma de selección)

Se trata de la etiqueta input con el atributo type con valor "radio" o "checkbox". Ambos controles pueden repetirse (duplicar el nombre), pero en el caso de los radios, cuando se marca un radio, automáticamente se desmarcan los demás elementos con el mismo nombre, por esta razón se puede decir que no admite enviar arreglos (1).

Contraseñas (password)

Con input type="password", no es posible ver el contenido, se usa para introducir contraseñas, y tendrían poco sentido en formularios con el método get, ya que se descubriría el contenido en la url.

Adjuntar ficheros (file)

Para poder adjuntar ficheros en un formulario se debe usar un control file (input type="file"), y obligatoriamente debe tratarse de un formulario con el método post y el atributo enctype="multipart/form-data".

Campos ocultos (hidden)

Estos campos no son visible, y por lo tanto no pueden modificarse (salvo si se usa javascript); suele usarse para elementos "constantes" (lo mismo se consigue con el atributo readonly) y que no se tiene intención de mostrar.

Botón submit

Cuando usamos botones submit, normalmente ponemos un value del tipo "enviar" o "enviar formulario", y es que este control es precisamente el encargado de esa función. Existen 2 formas de mostrarlos, con la etiqueta input o con la etiqueta button; en ambos casos debe usarse el atributo type="submit" (2), y en el caso de usar la etiqueta button, lo que se muestra no se pone en un campo value, ya que esta etiqueta consta de una pareja para el cierre(3).

Botón reset

Los botones reset sirven para reinicializar o resetear todos los campos del formulario. Nótese que no se trata de borrar los campos, ya que estos pueden tener un valor inicial (ya sea en el campo value de un campo de texto, como elementos seleccionados o checkeados).

Botón (genérico)

Con el atributo type="button", los botones son genéricos, y pueden usarse para lo que se quiera, como introducir en campos de texto valores específicos, comprobar contenidos, o modificar algunos atributos de sus elementos (disabled, checked, readOnly...)

Imágenes (¿botón submit?)

El control -input type="image"- es un tipo especial de entrada, y aunque se acostumbra a considerar como una simple variante de los botones submit, cuando se pincha en una imagen además de hacerse el envío del formulario, se envian también las coordenadas en donde se ha pinchado de la imagen. Supongo que en su origen, habría sido una variente de los mapas de imágenes, con la posibilidad de enviar datos adicionales.

Elementos adicionales

Los elementos adicionales nos permiten mejorar el aspecto y la funcionalidad de los formularios, agrupando controles en algunos casos, y ayudando a tomar el control en otros casos.

Etiquetas (label)

El elemento "label" permite activar elementos, modificando el atributo checked en checkboxes y radios, o dando el foco en los demás controles.

fieldset y legend

Fieldset crea una línea alrededor de los elementos que contiene, se complementa con legend (leyenda) que permite poner un texto para identificar al grupo de controles que contiene.

optgroup

Esta etiqueta sirve para agrupar opciones (etiquetas option), solo puede usarse dentro de un control select, mostrando las opciones encerradas entre esta pareja de etiquetas de forma destacada.

Envío

Los controles son los elementos destinados a enviar la información, pero debemos tener en cuenta donde y como se enviarán. El destino suele ser una página que se encuentre en el servidor, o directamente a nuestra cuenta de correo. Una tercera opción, válida solamente (en mi opinión) en una fase de pruebas, es el envío a un "javascript".

Primeras pruebas: envío a un script

No tiene mucho sentido enviar un formulario a un script, a no ser que se trate de alguna prueba, entonces vamos a probar un sistema de confirmación de envío... simplemente pondremos un control de entrada y un botón submit; el actión mostrará una alerta de confirmación de envío, pero antes aparecerá una ventana modal que nos pedirá la confirmación.

El código de este sencillo formulario es:

<form
	action="javascript: alert('Mensaje enviado correctamente')"
	method="get"
	enctype="text/plain"
	onsubmit="return confirm('Seguro que quiere enviar el formulario')"
>
<input type="checkbox" name="entrada" value="si" checked />
<input type="submit" value="probar" />
</form>

Envío simple con un fichero adjunto (por ejemplo una foto)

Los controles normales son de tipo texto (incluso los campos numéricos deben convertirse), solo existe la excepción de los campos file, cuyo contenido es un fichero (binario).

Para poder adjuntar ficheros deben cumplirse las siguientes condiciones: el método debe ser post, debe definirse el atributo enctype con el valor multipart/form-data y por supuesto, debe existir un control "file" con contenido válido.

Recepción

Sobre la recepción, está claro que dependerá del envío, y del lenguaje que se disponga en el servidor. En este tutorial, hablaremos de la recepción usando php y javascript.

Recepción mediante javascript

Es el sistema menos aconsejable porque es también el más condicionado. Solo vale si se tiene javascript activado y el método de envío es get (y enctype="text/plain").

El truco para recibir datos con javascript es leyendo la url, ya que cuando se envían datos por el método get a la página se le añade el carácter "?" (cierre de interrogación) seguido de los datos separados por el carácter "&" (ampersand).

url = location.search.substr(1).split("&");
for (i = 0, total = url.length; i < total; i ++)
	window[url[i].split("=")[0]] = url[i].split("=")[1];
/*
	Con estas líneas, al enviar un formulario con el método get,
con un campo nombre y otro campo ciudad, de tal modo que se fabrica una url así:
destino.html?nombre=Pepe&ciudad=Torremolinos,
obtenemos las variables de esta manera:
*/
var nombre="Pepe";
var ciudad="Torremolinos";

Recepción mediante php

Mediante el lenguaje php es mucho más sencillo, ya que el mismo lenguaje tiene variables "especiales" para el caso, del tipo array que se llaman $_GET y $_POST, asociadas a los respectivos métodos de envío/recepción.

A continuación presentamos un "receptor universal", que simplemente muestra los datos enviados:

<html>
<body>
<?
function listado($descriptor, $objeto, $nivel) {
	echo "<u>$descriptor</u>:<br/>\n";
	echo "<div style='border: 1px solid gray; margin-left: 1cm'>";
	echo "Datos $descriptor: (nivel: $nivel)<br />\n";
	foreach ($objeto as $item => $dato)	{
		echo "$item = $dato <br />";
		if (is_Array($dato) && ($nivel < 5) && ($item != $descriptor))
			listado($descriptor."[ ".$item." ]", $dato, $nivel + 1);
	}
	echo "</div>";
}

listado ("GET", $_GET, 0);
echo "<hr />";
listado ("POST", $_POST, 0);
echo "<hr />";
listado ("FILES", $_FILES, 0);
?>
</body>
</html>

Todos los ejemplos de este tutorial serán enviados a este receptor: receptor

Validación

La validación de un formulario es en ocasiones importantísimo, ya que podemos tener campos obligatorios, o guardar información en una base de datos, y no nos interesa tener que "administrar" esa base de datos para eliminar basura, o tampoco nos interesa que nuestro visitante "desconfíe" de nuestro formulario al ver que se trata de "una chapuza".

Para que un formulario pueda considerarse bueno, si necesitase validación, preferentemente debe ser doble, la primera en el navegador usando javascript, y la segunda en el servidor con el lenguaje que dispongamos en él.

Adicionalmente pueden implementarse otras validaciones puntuales, como validar que solo se inserten ciertos caracteres en campos concretos, o que el contenido de un campo tenga un formato especial, como los emails, o url's.

Validando en el navegador (javascript)

Vamos a tratar validaciones sencillas, tan solo comprobar que algunos campos tengan contenido, aunque los problemas más frecuentes en validaciones es debido a comprobaciones más complejas.

Las validaciones "generales" en el navegador se deben hacer en el envío; ¿Porqué se subraya "en el envío"? simplemente porque debemos "enviarlo" con el típico botón submit, pero ese botón provoca un evento del mismo nombre, y que se controla con el manejador de eventos onsubmit del formulario (etiqueta form).

El sistema es bastante sencillo, si el manejador de ese evento recibe el valor true (verdad), el formulario se envía, y si por el contrario recibe el valor false (falso), el formulario no se envía (se cancela el envío).

Es importante que el formulario sea enviado con un botón del tipo submit, aunque exista la alternativa de envío mediante un script (con el método submit() de los formularios), para asegurarnos que nuestra página sea accesible.

<form
	action="receptor.php"
	method="post"
	enctype="application/x-www-form-urlencoded"
	onsubmit="return dato.value != ''"
>
<label for="obligatorio" >Dato: (obligatorio)</label>
<input name="dato" id="obligatorio" type="text" />
<button type="submit" >Enviar dato</button >
</form >

Más posibilidades

La validación del ejemplo es un caso muy sencillo, pero los distintos controles tienen distintas formas de comportarse, por lo que es buena idea considerar el funcionamiento por separado. Los elementos donde se introducen datos por el teclado pueden ser muy sencillos si solo importa de que exista contenido, y vale en este caso el ejemplo anterior, pero en ocasiones se buscan caracteres especiales o alguna combinación de dígitos y/o letras, en donde es recomendable el uso de expresiones regulares, tema que en esta sección no desarrollaremos.

Otra forma de validar es a medida que se teclea. Para mejor información, recomiendo la página de Javier Blasco: Validar la entrada de datos en un formulario donde también puede verse el uso de expresiones regulares.

Control Select

Los controles select pueden validarse de distintas maneras; las opciones seleccionadas tienen un atributo: "selected", que se pone con valor true en el momento que se selecciona, también el elemento select tiene un atributo que indica el índice de la opción seleccionada (selectedIndex), y a la vez se puede consultar el atributo "value" del control.

La verdad es que estos controles son de muy fácil validación ya que las posibilidades de selección son estrictas. Creo que el único problema sería al dejar la primera de las selecciones reservada para mensajes del tipo "seleccione una opción", pero si el atributo value lo dejamos en blanco, la validación sería trivial:

<form onsubmit="return selector.value != ''" >
...
<select name="selector" >
<option value="" selected="selected" > Seleccione una opción </option>
<option value="1" > valor 1 </option>
<option value="2" > valor 2 </option>
</select >
...
</form >
Select multiple

En el supuesto caso de que el control select fuese multiple, o sea que admitiera más de una selección, podemos considerar más cosas, pero nos valdría el ejemplo de la validación con el campo value vacío. También podría tratarse de que no hubiera ninguna selección; en tal caso el atributo selectedIndex tendría el valor -1, pero si lo que nos interesa es que al menos se seleccionen más de un elemento, entonces deberemos trabajar un poco más nuestro script de validación:

function seleccionados(control) {
	marcados = 0;
	for (i = 0, total = control.options.length; i < total; i ++)
		marcados += (control.options[i].selected) ? 1 : 0;
	return marcados;
}

Con esta sencilla función que debemos colocar preferentemente en la cabecera de la página (head) en una sección script, podemos saber el número de opciones seleccionadas, con lo que la validación se simplificaría:

<form onsubmit="return seleccionados(selector) > 1" >
Radios

Los controles del tipo radio tienen otro tratamiento. En principio lo normal es que haya más de uno con el mismo nombre, y si consultamos el atributo value siempre obtendremos ese atributo del primero de los controles con el mismo nombre, aunque no esté marcado.

Cuando se marca un radio, automáticamente se desmarca el que anteriormente estuviera marcado. Para tener un radio marcado como predeterminado, se le debe añadir a la etiqueta el atributo checked:

<input type="radio" name="confirmar" value="si" />
<input type="radio" name="confirmar" value="no" checked="checked" />

Entonces la forma de validar sería comprobar si hay alguno "checked", recorriendo el array de radios con el mismo nombre. Debe considerarse que puede pasar que no exista ningún radio "checked" como predeterminado o que con javascript también se pueden desmarcar.

function chequeado(control) {
var marcado = false;
for (i = 0, total = control.length; i < total; i++)
	marcado = marcado || control[i].checked;
return marcado;
}

Sobre el uso de la función "chequeado()" creo que no es necesario dar explicaciones.

Checkboxes y otros arrays

El tratamiento de estos controles es igual al de los radios, ya que pueden estar "checked" o no; pero la posible dificultad para el trato de estos controles es que pueden existir más de uno con el mismo nombre chequeado (recuerdese que los radios como máximo puede haber uno "checked").

Como problema añadido tenemos que considerar que lenguajes como php necesitan que los nombres de los controles del tipo array terminen con un juego de corchetes. Por ejemplo, si queremos que nuestros visitantes nos indiquen los idiomas que hablan, el conjunto de checkboxes tendría que llamarse "idioma[]", y esa pareja de corchetes complica el sistema de validación, pero no demasioado, ya que basta conseguir que la función validadora los reconozca, y un truco sencillo para nuestro objetivo es tratar ese nombre como una cadena dependiendo del formulario, poniéndolo entre corchetes, por ejemplo:

onsubmit="return marcados(this['idioma[]']) > 0"

Ahora nuestra función se definiría así:

function marcados(control) {
	marcas = 0;
	for (i = 0, total = control.length; i < total; i++)
		marcas += (control[i].checked) ? 1 : 0;
	return marcas;
}

Para terminar indicar que esta última función sería exactamente igual en un select múltiple cambiando la coletilla ".checked" por ".selected".

Ficheros adjuntos

La validación de los controles del tipo file, pueden ser tan sencillos como los de texto, ya que se puede consultar el atributo value igual que los mencionados, pero lo que más interesa en estos controles es que tengan una determinada extensión (imágenes ".gif" o ".jpg", u otros tipos determinados). La complejidad de estas validaciones me han inducido a escribir otro artículo: Revisar las imágenes antes de subirlas, que en concreto trata el asunto de las imágenes; de comprobar a la vez las extensiones en la máquina del usuario como la validez y características de las mismas en el servidor.

Imágenes

Sobre los controles del tipo "image", no tiene sentido considerar la validación ya que su cometido es enviar las coordenadas de las mismas (donde se pulsa). Cuando enviamos la coordenada y la imagen no tiene nombre, las variables que se envían son x e y, pero si el nombre es imagen, en la url vemos (con el método get, "imagen.x" e "imagen.y". Para recibir esos valores con php, la variable sería: $_GET["imagen_x"]/["imagen_y"].

Juntando todo

Hasta ahora las validaciones las hemos hecho de solo un campo a la vez, pero si queremos validar todos los campos, simplemente tenemos que hacer la "conjunción" de todos los resultados...

function validar(formulario) {
	Ok =	(formulario.nombre.value != "")	&&
		(formulario.selector.value != "")	&&
		(seleccionados(formulario.selector) > 1)	&&
		(chequeado(formulario.radios)	&&
		(marcados(formulario["idiomas[]"]) > 0)
	return Ok;
}

Y la forma de uso es:

<form onsubmit="return validar(this)" >

Siempre pueden añadirse mensajes de alerta y posicionamiento o foco en los campos que no pasen la validación, pero esos añadidos quedan a gusto del webmaster.

Validando en el servidor

Vamos a considerar tres casos sencillos para validar, que se haya marcado algún control del tipo checkbox o radio, o que no tenga valor un control determinado, o que no se haya adjuntado un archivo en un campo file.

Usaremos en el servidor el lenguaje php, que dispones de algunas facilidades para estas validaciones. Según el método que usemos en el envío, se dispone de sendos arrays $_GET y $_POST, y para el caso de adjuntos $_FILES.

Control de datos erróneos (variable sin contenido):

<?
// formulario con campo nombre obligatorio:
$errorNombre = ($_POST["nombre"] != "");
?>

Control de dato inexistente (radio o checkbox sin marcar):

<?
// formulario con campo trato del tipo checkbox (o radio):
$errorTrato = isset($_POST["trato"]);
?>

Control de adjunto inexistente (campo file sin contenido):

<?
// formulario con campo foto del tipo file:
$errorFoto = isset($_FILES["foto"]);
?>

Ahora juntamos todo y si hay fallos volvemos:

<?
if ($errorNombre || $errorTrato || $errorFoto)
	header("Location: ".$_SERVER["referer"]);
?>

Siempre puede refinarse el sistema, añadiendo mensajes en el formulario principal, en los casos que no pase la validación, por ejemplo usando sesiones.

Otras acciones a considerar: habilitación, foco, borrado...

En esta sección aclararemos algunas dudas básicas de manipulación de los distintos controles de un formulario.

Habilitar un control

Aunque este asunto concierne más al lenguaje javascript, es otro problema habitual de los desarrolladores web. No es recomendable depender mucho de estos scripts porque nuestros visitantes pueden deshabilitarlo (no me canso de decirlo). En muchos casos debemos asociar distintas acciones a algún evento, y lo normal es que se trate de activarlos con los cambios en los controles. El primer ejemplo que se me ocurre es tener el botón submit deshabilitado y al llenar un campo habilitarlo:

<script type="text/javascript" >
function deshabilitar()	{
	document.forms.formulario.envio.disabled = true;
}
window.onload = deshabilitar;
</script >

Estas cosas hay que tratarlas con pinzas, así que esperamos a abrir la página para deshabilitar el botón "envío" de nuestro formulario, para que si nuestro visitante tiene deshabilitado javascript pueda de todos modos enviar el formulario, en este caso debemos validar si fuese necesario solo en el servidor.

Ahora veremos lo fácil que es habilitar nuestro botón con nuestro control:

<input type="text" name="nombre" onchange="envio.disabled = this.value == ''" />
Seleccionar en un control select

Si queremos que una opción de un control select quede seleccionada, simplemente tenemos que asignar al atributo value del elemento, el valor del atributo value de la opción que deseemos. Para comprender mejor el "trabalenguas" que acabamos de leer, vamos a seleccionar un elemento a partir de un script. En principio describimos el control:

<form name="ejemplo" >
<select name="selector" >
<option value="" >Seleccione un mueble</option >
<option value="cama" >cama</option >
<option value="mesa" >mesa</option >
<option value="silla" >silla</option >
</select >
</form >

Ahora supondremos que existe algún elemento activo (no necesariamente en el formulario) con el que vamos a dejar marcada la opción "silla"

<p >Seleccionamos una
<span onclick="document.forms.ejemplo.selector.value = 'silla' " >silla</span >
...
</p >
Si no valida email cancelar el envío, mostrar el error, limpiar y dar foco al campo

Para la validación de emails (y otros campos de texto) se suelen usar expresiones regulares, tema en el que no vamos a profundizar, pero sí explicaremos la metodología.

De las expresiones regulares nos centraremos en su uso con javascript. Empezaremos declarando la expresión que nos servirá para chequear el email, que es el objeto de esta sección:

var _es_email = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;

Para comprobar que un texto "encaja" en la expresión que hemos creado, debemos usar el método test. Cuando vale se obtiene el valor lógico true (vale). Para terminar definiremos un sencillo formulario con la funcionalidad esperada, junto con un mensaje oculto que se mostrará en caso de que falle la validación:

<form method="get" action="javascript: alert('email válido, podemos enviar el formulario...')"
onsubmit="return validaEmail(email)">
<label>email: <input type="text" name="email" /></label>
<div id="capa_oculta" style="display: none; color: red">
Debe volver a llenar el campo e-mail
</div>
<button type="submit">enviar</button>
</form>

Nótese que nos referimos al elemento del formulario y no a su valor, para darle el foco si no pasa la validación.

var _es_email = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
function validaEmail(cual) {
	vale = _es_email.test(cual.value);
	if (!vale)	{
		document.getElementById("capa_oculta").style.display = "block";
		cual.value = "";
		cual.focus();
	}
	return vale;
}

Siempre que tengamos que devolver un valor y a la vez realizar otras acciones (en este caso mostrar la capa oculta y dar el foco al campo), la instrucción return debe ser la última, ya que si hubiera más acciones se omitirían.

Reseteo y envío por script

En el caso anterior hemos limpiado un campo concreto, pero hay ocasiones que queremos limpiar todos los campos. Si bien existen los botones del tipo reset, y es lo más aconsejable (siempre debemos considerar que quienes visiten nuestra página pueden desactivar javascript), es frecuente ver ese tipo de comportamiento desde elementos que no son botones, incluso que se encuentren fuera del formulario, para eso existe el método reset(); y para el envío el método submit().

reset() es un método que no limpia el formulario sino que lo deja en el estado inicial, por ejemplo, si tenemos un campo con valor inicial "Introduzca su nombre", después de ejecutar el método vuelve a tener ese mensaje. Véase como se quedaría:

<form name="ejemplo" action="javascript: alert('enviando formulario')" >
<label >Nombre: <input type="text" name="nombre" value="Introduzca su nombre" ></label>
</form >
<img alt="reset" src="reset.gif" onclick="document.forms.ejemplo.reset()" />
<img alt="submit" src="submit.gif" onclick="document.forms.ejemplo.submit()" />

Para el supuesto caso de usar estos métodos, debe considerarse que se trata de acciones "forzadas", y no tendría ningún sentido usar los manejadores de eventos onsubmit y onreset (este último no ha sido considerado en este texto pero es fácil descubrir su funcionalidad).

Un ejemplo

Como ejemplo mostraremos un sencillo formulario donde se muestran unos pocos controles, aunque suficientes para pedir/obtener información.

Formulario básico de contacto

Vamos a mostrar un formulario básico de contacto, copiado del artículo Páginas multilenguaje con javascript, y aprovecharemos para mostrar el funcionamiento de algunos controles y etiquetas relacionadas. Puede verse el código del formulario y de los scripts javascript asociados en este enlace: formEjemplo.txt, el mismo fichero es el que se encuentra incluído a continuación (instrucción include del lenguaje php); los estilos pueden verse en el código fuente de esta misma página.

idioma idioma idioma Formulario de Contacto

idioma idioma idioma Contact Form

idioma idioma idioma Forme de Contact

Idiomas que conoces Languages that you know Langues que vous savez

Vamos o omitir comentarios sobre la selección del lenguaje, porque en el anterior enlace se explica (remítase a él en caso de estar interesado). Sobre los controles, hay tres entradas de texto simple (input type="text"), otras tres entradas de selección (input type="checkbox"), una entrada de texto con saltos de línea (textarea) y un botón del tipo submit para el envío del formulario. Cada control (exceptuando el botón) tiene un titular asociado, que no es otra cosa que una etiqueta "label", y le hemos asignado un orden de tabulación; hemos alterado el orden normal de esa tabulación solo para que sirva de ejemplo.

Al tener un campo de texto con saltos de línea que podría ser extenso, lo aconsejable es que el método del formulario sea post, y al no llevar datos adjuntos, el enctype no debe ser multipart-form/data, por lo que nos hemos decantado por application/x-www-form-urlencoded.

Los controles llevan un nombre (atributo name) equivalente a lo que se ve como título, salvo en el caso del idioma, porque al ser un array que será procesado por php, al nombre le hemos añadido un juego de corchetes (name="idiomas[]").

Ya puede probar el envío del formulario, le aconsejo que vea los distintos comportamientos ya sea rellenando todos los campos u omitiendolo en alguno de ellos. También pruebe como se procesan los arrays.

Notas
  1. Aunque hagamos la afirmación de que no pueden existir arrays de radios, Puede haber un grupo de radios con nombre "radio[0]", otro con nombre "radio[1]"; y con este ejemplo, procesando el formulario con php sería considerado como el array "radio".
  2. Por defecto, el atributo type para los botones debería ser "submit", pero inexplicablemente no todos los navegadores respetan esa norma.
  3. Con esta particularidad de las etiquetas button, también podríamos poner imágenes y conseguir mejores diseños.