Otro ejemplo de formulario dinámico con campos opcionales

Otra forma de crear un formulario con campos que se muestran y se esconden dependiendo de las acciones del usuario, utilizando DHTML con Javascript cross browser.
El ejemplo que vemos acontinuación es una variación del expuesto en el artículo Un formulario con campos que se esconden con DHTML, pero ésta vez, dependiendo de la selección que hagamos en un campo select del formulario, mostrará más o menos campos al visitante.

Para ello creamos una caja de selección dentro del formulario y le decimos que, cuando se cambie el valor del campo, se ejecute la función en javascript "expandir_formulario()":

<select size="1" name="personas" onchange="expandir_formulario()" >
<option value="0">?</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>

La función javascript comprobará la selección que hemos elegido y dependiendo de ésto activará o desactivará las diferentes capas del formulario.

function expandir_formulario(){
if (document.f1.personas.value == "0"){
    xDisplay('capaexpansion', 'none')
    xDisplay('capaexpansion2', 'none')
    xDisplay('capaexpansion3', 'none')
    xDisplay('capaexpansion4', 'none')
    xDisplay('capaexpansion5', 'none')
}
if (document.f1.personas.value == "1"){
    xDisplay('capaexpansion', 'block')
    xDisplay('capaexpansion2', 'none')
    xDisplay('capaexpansion3', 'none')
    xDisplay('capaexpansion4', 'none')
    xDisplay('capaexpansion5', 'none')
}

if (document.f1.personas.value == "2"){
    xDisplay('capaexpansion', 'block')
    xDisplay('capaexpansion2', 'block')
    xDisplay('capaexpansion3', 'none')
    xDisplay('capaexpansion4', 'none')
    xDisplay('capaexpansion5', 'none')
}
if (document.f1.personas.value == "3"){
    xDisplay('capaexpansion', 'block')
    xDisplay('capaexpansion2', 'block')
    xDisplay('capaexpansion3', 'block')
    xDisplay('capaexpansion4', 'none')
    xDisplay('capaexpansion5', 'none')
}
if (document.f1.personas.value == "4"){
    xDisplay('capaexpansion', 'block')
    xDisplay('capaexpansion2', 'block')
    xDisplay('capaexpansion3', 'block')
    xDisplay('capaexpansion4', 'block')
    xDisplay('capaexpansion5', 'none')
}
if (document.f1.personas.value == "5"){
    xDisplay('capaexpansion', 'block')
    xDisplay('capaexpansion2', 'block')
    xDisplay('capaexpansion3', 'block')
    xDisplay('capaexpansion4', 'block')
    xDisplay('capaexpansion5', 'block')
}
}

Nota: Posiblemente hubiera sido más elegante haber metido todos los valores de los identificadores de las capas en un array y haber realizado un recorrido por el array mostrando las capas u ocultándolas según el índice marcado en el select.

Se puede ver en el anterior código que se ha hecho uso de una funcion de las librerías X Library, llamada xDisplay(). Esta función se tiene que definir en el código del programa y para ello incluiremos un script javascript externo que contiene el código de la función. La procedencia de este archivo también se explicó en el artículo Un formulario con campos que se esconden con DHTML.

<script type='text/javascript' src='formexp.js'></script>

También necesitaremos un código CSS para definir los estilos iniciales de las capas. Posteriormente, la activación de cada capa vendrá dada por el atributo display de la CSS.

<style type="text/css">
#capainicio{
position:relative;
}

#capaexpansion{
position:relative;
display:none;

}

#capaexpansion2{
position:relative;
display:none;

}

#capaexpansion3{
position:relative;
display:none;

}

#capaexpansion4{
position:relative;
display:none;

}

#capaexpansion5{
position:relative;
display:none;

}

#capafinal{
position:relative;

}
</style>

Esperamos que este ejemplo haya resultado sencillo. Recordamos que las explicaciones detalladas se ofrecieron ya en un artículo anterior que se llama Un formulario con campos que se esconden con DHTML.

Podemos ver ejemplo en marcha.

Existe un zip con los materiales usados en este artículo.

Autor

Francisco Javier Sánchez

Programador web

Compartir

Comentarios

franklis

09/5/2006
esto funciona perfectamente en el explorer de window pero en linux que debo de realizar para que el mosilla reconsca el xDisplay

Moises

25/5/2006
Muy bueno su articulo, pero en el Internet Explorer 6 con la ultima actualización y tambien el Internet Explorer 7 (Beta 2), esto no funciona tan eficientemente.

Si tienen alguna manera de corregir ese error y publicarlo se los agradeceria.

Otra cosa, no se puede simplemente poner el campo que se ve pero que no sea editable hasta que selecciones la opcion que lo hara editable?

n0l0s3

12/4/2009
boton de opcion
Si cambio la lista por un boton de opcion, ¿seria asi?
(mi email es nolose@nolose.es) gracias!!!

<input name="personas" type="radio" onClick="expandir_formulario()" value="0" checked >
0
<input name="personas" type="radio" onClick="expandir_formulario()" value="1">
1
<input name="personas" type="radio" onClick="expandir_formulario()" value="2">
2

juan

21/8/2009
checa este formulario
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Calc</title>

<script type="text/javascript">
<!--
num=0;
function crear(obj) {
num++;
fi = document.getElementById('fiel'); // 1
contenedor = document.createElement('div'); // 2
contenedor.id = 'div'+num; // 3

fi.appendChild(contenedor); // 4

ele = document.createElement('input'); // 5
ele2 = document.createElement('input'); // 5
ele3 = document.createElement('input'); // 5
ele4 = document.createElement('input'); // 5

ele.type = 'text'; // 6
ele.name = 'item[]'; // 6
ele.size = 5;
contenedor.appendChild(ele); // 7

ele2.type = 'text'; // 6
ele2.name = 'desc[]'; // 6
ele2.size = 100;
contenedor.appendChild(ele2); // 7

ele3.type = 'text'; // 6
ele3.name = 'precio[]'; // 6
ele3.size = 7;
ele3.onkeyup = function(){addHiddenNeto(this.value)}
ele3.onfocus = function(){setHiddenNeto(this.value)}
contenedor.appendChild(ele3); // 7



ele4.type = 'button'; // 6
ele4.value = 'Borrar'; // 8
ele4.name = 'div'+num; // 8
ele4.id = num;
ele4.onclick = function () {borrar(this.name, this.parentNode)} // 9
contenedor.appendChild(ele4); // 7
}

function borrar(obj, getP) {
P = getP.childNodes[2].value;
if(P == ""){P = 0;}
document.form1.neto.value = parseFloat(document.form1.neto.value)-parseFloat(P);
fi = document.getElementById('fiel'); // 1
fi.removeChild(document.getElementById(obj)); // 10
setNeto();
}
function addHiddenNeto(n){
if(n==""){n=0;}
document.form1.neto.value = document.form1.neto.value-document.form1.hiddenNeto.value;
document.form1.hiddenNeto.value = n;
document.form1.neto.value = roundNumber(eval(parseFloat(document.form1.neto.value)+parseFloat(document.form1.hiddenNeto.value)),2);
setNeto();
}
function setHiddenNeto(n){
if(n==""){n=0;}
document.form1.hiddenNeto.value = n;
setNeto();
}
function setNeto(){
if(document.form1.descuento.value == ""){document.form1.descuento.value = 0;}
document.form1.tsi.value = roundNumber(parseFloat(document.form1.neto.value)-parseFloat(document.form1.descuento.value),2);
//Se tiene que calcular por 0.19 ya que la matematica para 19% es esa.
document.form1.tci.value = roundNumber(parseFloat(document.form1.tsi.value)+(parseFloat(0.19) * parseFloat(document.form1.tsi.value)),2);
}
function roundNumber(rnum, rlength) { // Arguments: number to round, number of decimal places
return Math.round(rnum*Math.pow(10,rlength))/Math.pow(10,rlength);
}
-->
</script>

<style type="text/css">
<!--
body {
background-color: #797979;
}
.Estilo4 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #999999; }
.Estilo14 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 16px; color: #666666; font-weight: bold; }
.Estilo45 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #333333; }
.Estilo49 {font-family: Verdana, Arial, Helvetica, sans-serif}

.Estilo36 {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 18px;
color: #000000;
}
.Estilo38 {font-size: 12px}
.Estilo48 {color: #999999}
.Estilo4 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #999999; }
-->
</style>

</head>
<body>

<form name="form1" method="post" action="algo.php">
<input type="hidden" name="hiddenNeto" value="0">
<table width="960" height="415" border="0" align="center" bgcolor="#FFFFFF">
<tr>
<td height="24">&nbsp;</td>
<td height="24" colspan="9">&nbsp;</td>
<td width="155" rowspan="2"><div align="center"></div></td>
</tr>

<tr>
<td height="107">&nbsp;</td>
<td height="107" colspan="9">&nbsp;</td>
</tr>
<tr>
<td width="16" height="0"></td>
<td colspan="10"><table width="881" border="0" align="center">
<tr>
<td width="13">&nbsp;</td>
<td width="58"><div align="center" class="Estilo4">Item</div></td>
<td width="628"><div align="center" class="Estilo4">Descripción</div></td>
<td width="82"><div align="center" class="Estilo4">Precio</div></td>
<td width="78"><span class="Estilo4">Borrar</span></td>
</tr>
<tr>
<td colspan="5"><fieldset id="fiel"></fieldset><input name="button" type="button" onClick="crear(this)" value="Crear" /></td>
</tr>
</table></td>
</tr>


<tr>
<td height="25" rowspan="5">&nbsp;</td>
<td width="86" rowspan="5">&nbsp;</td>
<td width="102" rowspan="5">&nbsp;</td>
<td width="102" rowspan="5">&nbsp;</td>
<td width="102" rowspan="5">&nbsp;</td>
<td width="102" rowspan="5">&nbsp;</td>
<td width="102" rowspan="5">&nbsp;</td>
<td width="113">&nbsp;</td>
<td colspan="2">
<label> </label>
<div align="center">
<input name="fin" type="checkbox" id="fin" onClick="calcular(this)" value="entregado">
</div> </td>
<td class="Estilo45">Fin de proceso </td>
</tr>
<tr>
<td width="113"><div align="right">
<input name="Calcular" type="button" value="Calcular" onclick="setNeto()" />
</div></td>
<td colspan="2" class="Estilo45">Neto</td>
<td>
<label>
<input name="neto" type="text" id="neto" value="0" readonly>
</label>
</td>
</tr>
<tr>
<td width="113">&nbsp;</td>
<td colspan="2" class="Estilo45">Desc</td>
<td><input name="descuento" type="text" id="descuento" onkeyup="setNeto()"></td>
</tr>
<tr>
<td width="113">&nbsp;</td>
<td colspan="2" class="Estilo45">TSI</td>
<td><input name="tsi" type="text" id="tsi" readonly></td>
</tr>
<tr>
<td width="113">&nbsp;</td>
<td colspan="2" class="Estilo45">TCI</td>
<td><input name="tci" type="text" id="tci" readonly></td>
</tr>
<tr>
<td height="38">&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td><input type="submit" name="button2" id="button" value="Registrar" /></td>
</tr>
</table>
</form>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>

Luisensko

07/7/2010
El formulario sólo funciona con el atributo name=f1
Tengo un problema con este código: la ocultación o visualización de campos sólo funciona si el formulario tiene el nombre "f1", lo cual no es muy útil, ya que tengo varios formularios que por otras razones tienen que tener otros nombres. Por otra parte, no le veo utilidad a la capainicio y capafinal. Sin necesidad de crear estas capas, el formulario funciona perfectamente.

pipomans

22/12/2011
Gracias
Muy ameno y minimalista, gracias...

Kerly

12/3/2013
Como guardar los datos de los campos de textos que se generan
Hola que tal como estas, me gustaría saber como hago para guardar los datos que introduzca en los campos de textos en base de datos.

SlasherWesker

06/2/2014
Mysql
Que tal use el codigo pero como seria para agregar los diferentes nombres a una base de datos? me podrian asesorar. Gracias de antemano

frexion

22/2/2014
Ayuda
Necesito que esto aparezca en dos campos Select y no lo logro debido a que solo hace caso al primer campo que le asigne los valores. Como puedo lograr tener eso en dos campos selects independientes en mi caso uno con la etiqueta ADULTOS y otro de MENORES

Arce

20/11/2014
Universidad
Con un ciclo como sería? Es decir, que se haga automaticamente.

Cesar

01/12/2014
Para juan comentario del 21/8/2009 "checa este formulario"
El codigo de generacion de los campos de manera dinamica me parece genial la forma en que funciona, sin embargo tengo un problema que no he podido hacer que me guarde el contenido de los campos en la BD, ya habia logrado guardar en una prueba previa en una BD pero por un problema con el SO, y las prisas solo respalde lo mas importante, y no ese codigo y ya no recuerdo como le hice para que funcionara correctamente.

Seguire checando por que si me gustaria utilizar este codigo en un proyecto.

Saludos

eleazar_r

14/1/2016
Excelente
Funciona perfectamente.
Gracias por el aporte....

Marcos Villavicencio Gonzalez

25/8/2017
EXPERIENCIA PERSONAL
hola, imagino que en su momento este código fue de gran ayuda :)
pero ahora en 2017 me encontré con esta solución en mi empleo
y es un dolor de cabeza darle mantenimiento a esa función, tal ves nunca se imaginaron que agregarían
20 capas o mas en las que si se agrega una mas el código de cada función también crece desmesuradamente
la forma en que soluciones ese problema es el siguiente
ocutarCapas() // agrego solo las capas nuevas o en su defecto las elimino
y la función de abajo es dinamica
#############################################
function expandir_servicios(obj){
var id_subservicio = parseInt(obj.value);

if (id_subservicio === 0){
ocultarCapas();
}else{
ocultarCapas();
xDislpay("capaexpansionestados", "block");
xDislpay("capaexpansion" + id_subservicio, "block");
xDislpay("capaexpansionobs", "block");
}
}
##################################################