Añadir campos a un formulario dinámicamente con JQuery
Publicado en June 10, 2009 by Damian

En uno de mis ultimos proyectos tuve la necesidad de crear un formulario donde el cliente pudiera añadir campos de texto a medida que lo fuera necesitando, y a su vez quitarlos si ya no le eran necesarios.
Esto se puede realizar de una forma muy sencilla con JQuery. Suponiendo que tenemos el siguiente código HTML
<form id="form" name="form" method="post" action="index.php">
<div id="material_comprado" > </div>
<h1>Compra de material</h1>
<p>Si es necesario añade el material a comprar</p>
<div id="div_1">
<label>Material de compra
<span class="small">Añade los materiales</span>
</label>
<input type="text" name="materiales[]" id="materiales1" style="width:200px;" /> <span style="float:left;padding: 8px 0px 8px 8px;">Cantidad:</span> <input type="text" name="cantidadmateriales[]" style="width:40px;" /><input class="bt_plus" id="1" type="button" value="+" /><div class="error_form"></div>
</div>
<button type="submit" class="boton">Save</button>
<div class="spacer"></div>
</form>
</div>
Con este código y añadiendole un poco de estilo tendriamos un pequeño formulario como el que muestra la imagen.
Ahora solo queda añadir unas cuantas lineas de JQuery para que funciones:
//ACA le asigno el evento click a cada boton de la clase bt_plus y llamo a la funcion addField
$(".bt_plus").each(function (el){
$(this).bind("click",addField);
});
});
function addField(){
// ID del elemento div quitandole la palabra "div_" de delante. Pasi asi poder aumentar el número. Esta parte no es necesaria pero yo la utilizaba ya que cada campo de mi formulario tenia un autosuggest , así que dejo como seria por si a alguien le hace falta.
var clickID = parseInt($(this).parent('div').attr('id').replace('div_',''));
// Genero el nuevo numero id
var newID = (clickID+1);
// Creo un clon del elemento div que contiene los campos de texto
$newClone = $('#div_'+clickID).clone(true);
//Le asigno el nuevo numero id
$newClone.attr("id",'div_'+newID);
//Asigno nuevo id al primer campo input dentro del div y le borro cualquier valor que tenga asi no copia lo ultimo que hayas escrito.(igual que antes no es necesario tener un id)
$newClone.children("input").eq(0).attr("id",'materiales'+newID).val('');
//Borro el valor del segundo campo input(este caso es el campo de cantidad)
$newClone.children("input").eq(1).val('');
//Asigno nuevo id al boton
$newClone.children("input").eq(2).attr("id",newID)
//Inserto el div clonado y modificado despues del div original
$newClone.insertAfter($('#div_'+clickID));
//Cambio el signo "+" por el signo "-" y le quito el evento addfield
$("#"+clickID).val('-').unbind("click",addField);
//Ahora le asigno el evento delRow para que borre la fial en caso de hacer click
$("#"+clickID).bind("click",delRow);
}
function delRow() {
// Funcion que destruye el elemento actual una vez echo el click
$(this).parent('div').remove();
}
Como siempre debemos añadir la ultima version de JQuery y luego nuestro script.
<script type="text/javascript" src="jquery.addfield.js"></script>
Este mismo ejemplo se puede aplicar en cualquier otro lado, solo es cuestion de jugar un poco. Espero que les haya gustado. Saludoss
Ejemplo Online
Descargar Ejemplo
Links Sponsors
Tags: formularios, JQuery
Categoría: JQuery, Tutoriales














Con tu lector preferido.
Via Email.
Por Twitter.
muy buena explicación,
Gracias por la info.
gracias,me ha servido
para q tiene q ver esto
eq(1) no se entiende bien
http://docs.jquery.com/Traversing/eq#index
Hola!!!
Me gusta mucho tu ejemplo y lo pienso utilizar para un software de manejo de inventario.
Conozco de php pero apenas me inicio en Javascript y más concretamente en Jquery.
Me gustaría saber qué plugin de autosuggest que mencionas utilizaste.
Gracias de antemano.
http://blog.timersys.com/recursos/240-plugins-para-jquery-lo-mejor-de-lo-mejor/
Ahi podes encontrar unos cuantos plugins, tan solo tenes que elegir el que mejor se adapte a tus necesidades.
Hola.
andaba buscando hace tiempo algo como esto pero tengo una duda que no se si es que ando espeso o que se me escapa algo.
¿y como recupero los datos generados para insertarlos en mysql?
En este ejemplo seria recorriendo el array materiales[]
while($i=0; $i < count($materiales); $i++){
mysql_query("INSERT INTO BLABLA (dato) VALUES ('$materiales[$i]')");
}
Saludos!!
Muchas gracias. voy a probarlo ahora mismo
con el while me daba un error de sintaxis en la primera linea. asi que puse un for ( que ni idea de que es por cierto ), total la cosa quedo asi:
for ($i=0; $i < count($materiales); $i++){
mysql_query("INSERT INTO BLABLA (dato) VALUES ('$materiales[$i]')");
}
y por lo menos dos lineas que inserte me las metió en la base de datos.
Muchas gracias nuevamente. Por cierto puedo usar tu código para la versión publica de Factusyn?
Hola otra vez.
ando liado insertado el script y adaptandolo a las necesidades de factusyn pero mis conocimientos de javascritp y jquery son muy limitados. si te incordio mucho simplemente ignora este comentario o no lo publiques y lo entenderé. Mira lo que necesito son varias cosas:
1- uso jquery.autocomplete y al insertar una segunda linea deja de funcionar autocomplete
2- me gustaría insertar un td en vez de texto en una capa
3- al insertar una linea calcula los totales de esa linea y en la segunda tampoco me calcula nada.
si quieres verlo en vivo esta aquí:
http://www.factusyn.es/Scripts/Archivos/Demos/Factusyn5/
en facturas de venta al insertar una factura nueva ( usuario: Demo
password: demo
No hay problema, usalo. Un mención a la web en el código fuente tampoco me molestaria
El código era for y no while, lo que pasa que era muy tarde y ni mire lo que puse. Gracias por comentarlo. Un saludo
Nacho, solo podes tener un id único.
sumalinea($(‘#cantidad’).val(), $(‘#precio’).val(), $(‘#dcto’).val());return false;
Deberias modificar los id de dichos campos tb para que no se repitan.
no tendras algo de código utilizando el script para mirar como hacer mas cosas?
si quieres te pongo mejor en los créditos ya que esto me supone muchísimo trabajo simplificado. dime que quieres que ponga y lo pongo.
Mi código es exactamente el que está en el ejemplo con la unica diferencia de que le añado un evento de autosuggest a cada nuevo campo que creo.
//adding autosugges property
var options = {
script: “get_materiales.php?limit=6&”,
varname: “materiales”,
json:false,
maxresults:10,
timeout:9999999,
noresults:’Ingresar nuevo material a la base de datos’
};
var as3 = new bsn.AutoSuggest(‘materiales’+newID, options);
}
Como podes ver uso ‘materiales’+newID para asi nunca repetir los ids y no crear errores.
Para ver el ejemplo funcionando podes ver mi programa
Saludoss
Nada que soy inutil perdio.
te apetece colaborar en factusyn? y das tu el soporte y hosting a america?
Te agradezco nacho, pero actualmente no tengo tiempo. Saludos y suerte en tu proyecto!
Hola otra vez. perdona que soy muy pesado y tienes que estar hasta las narices de mi ya.
te importaria pasarme una copia del get_materiales.php ( cambiando las consultas reales claro. que al final como no me veo capaz de usar mi autocomplete me pase al tuyo que ademas es ma bonico s. y estoy intentando mostrar resultados pero no pasa nada
hola, disculpa la molestia, cómo puedo hacer para leer los elementos creados desde javascript, es decir, quiero un javascript con el que pueda lanzar un alert por ejemplo, para poder validar los datos.
De antemano gracias
Los elementos se leer de la misma forma que si fueran creador en PHP. alert($(‘#idDelElemento’).val()); Saludos
Hola damian.
ya tengo funcionando todo excepto el calculo del total sobre la segunda linea.
me podrías echar una manica?
http://www.factusyn.es/Scripts/Archivos/Demos/Factusyn5/test/dinamic/
ya se que me vas a decir que le tengo que dar un id a los subtotales en jquery.addfield.js pero es que no tengo ni idea de donde meter ese id.
los calculos los meto usando una funcion:
function calculo(cantidad,precio,inputtext,totaltext){
/* Parametros:
cantidad – entero con la cantidad
precio – entero con el precio
inputtotal – nombre del elemento del formulario donde ira el total
*/
//restamos lo que habia en ese input por si cambiamos parametros
gndtotal= totaltext.value-inputtext.value;
// Calculo del subtotal
subtotal = precio*cantidad;
inputtext.value=subtotal;
//Calculo del total
total = eval(gndtotal);
totaltext.value = total + subtotal;
}
y llamo a esa función mediante un onkeyup en un imput:
input type=”texto” name=”cantidad[]” id=”cantidad1″ value=”1″ style=”width:40px;” onkeyup=”calculo(this.value,precio1.value,subtotal1,total);”/
si quieres ver el jquery.addfield.js que uso esta aquí:
http://www.factusyn.es/Scripts/Archivos/Demos/Factusyn5/test/dinamic/jquery.addfield.js
al final me voy a hacer un experto en jquery con la tonteria XD ( empiezo a entender el código poco a poco ).
en serio muchisimas gracias por tu ayuda pasada, presente y futura estoy aprendiendo un monton
Hola me parece muy bueno tu explicacion, cambie el campo texto por un menu desplegable que lee los materiales desde una base de datos pero al momento de querer agregar dos articulos mas ya no se puede eliminarlos primeros es decir en lugar de poner el signo – pone el + cual es la razon.
De antemano muchas gracias.
vale creo que ya lo tengo. necesito cambiar los parámetros del onkeyup. estoy probando algo así
$newClone.children(“input”).eq(1).attr(“id”,’materiales’+newID).val(”).attr(“onblur”,’calculo(cantidad2.value,precio2.value,subtotal2,total)’);
pero me da que la sintaxis no esta bien o algo esta fallando por que no me cambia los valores.
en principio estoy poniendo un 2 a la fuerza pero realmente tendría que usar el +newID.
donde puedo encontrar un manual de esto??
Para no complicarse tanto en sus proyectos, y tener que programar todo ustedes pueden usar algun plugin que realize lo que busquen. Hay uno muy bueno llamado JQuery dynamic form que permite clonar selectes, textarea, etc
Y además incluye varias opciones.
y fin. aquí pongo el código usado por si alguien lo necesita, con esto nos elimina el onblur que ya existía por si las moscas y mete uno nuevo
$newClone.children(“input”).eq(1).removeAttr(“onblur”).attr({“id”:’materiales’+newID,”onBlur”:”calculo(cantidad2.value,precio2.value,subtotal2,total);”}).val(”);
$newClone.children(“input”).eq(2).attr({“id”:’cantidad’+newID,”onKeyUp”:”calculo(this.value,precio2.value,subtotal2,total);”}).val(‘1′);
Putas mayúsculas 20 horas perdidas mirando por medio mundo distintos millones de códigos y solo estaba fallando que no ponía mayúsculas en onBlur y en onKeyUp. menudo churro de documentación que tiene jquery.
Bueno con esto ya me despido que a damian lo tengo frito.
por cierto damian respecto a tu ultimo comentario. si solo usamos plugin de jquery genéricos aparte de saturar la web con tonterías innecesarias no aprendemos nada.
jair seguramente tienes que cambiar el eq(1) por otro
//asigno un nuevo id al boton de eliminar
$newClone.children(“input”).eq(6).attr(“id”,newID)
el eq dichoso dice la posición donde esta el botón o el input si cambiaste el input por un select seguramente tendrás que restar un numero, en mi caso el boton – esta en la 6ª posición con lo que cambio el numero por un 6, en tu caso supongo que sera un 1 si tienes un select y un imput si te equivocas en el numero en la primera linea creo que si sale el eliminar pero en el resto solo salen + ( también me volví loco con ese tema al insertar mas inputs, no se si será así realmente pero es la deducción a la que llegue después de tanto tocar y tocar el código )
Hola gracias por tu aportacion me fue de gran ayuda
Saludos.
Como están? tengo dos problemas:
1º como meter los datos en un mysql, esto de
while($i=0; $i < count($materiales); $i++){
mysql_query("INSERT INTO BLABLA (dato) VALUES ('$materiales[$i]')");
}
no me funciona, tampoco el for…, yo uso php, cual sería la sentencia?
2º es (el link de prueba de nacho ya no anda) como logro colocar un campo que vaya sumando lo que vamos introduciendo (subtotal, por así decirlo).
Será que alguien puede ayudarme con esto? Muchas gracias desde ya.