Formularios Dinámicos 2
En esta ocasión les quiero compartir unas funciones que tratan de automatizar y simplificar los formularios dinámicos. Es una idea original de "DevelopArts" y espero que sea de ayuda a quienes nos visitan.
La idea es lograr algo parecido a lo siguiente:
Agregar Linea +
Como podemos ver, la idea es simple y es parecida al Artículo anterior, que para los que lo hayan usado, se habrán dado cuenta que presenta un problema cuando queremos meter una linea con muchos campos complejos (Select con muchos datos, Áreas de Texto, etc) el código crece exponencialmente y programar todos esos campos en JavaScript es verdaderamente aburrido, y cada modificación se convierte en un análisis de composición de árbol.
Para solventar el problema me he dado a la tarea de crear unas funciones que tratan de automatizar en lo posible la adición de lineas dinamicamente, pero no solo eso, sino que las lineas sean HTML común y corriente, escondido en alguna parte de la página, con lo que nos ahorraremos muchísimas lineas de código y además quedará mucho mas claro para cuando necesitemos realizar modificaciones.
Las funciones en cuestión son las siguientes:
// Variable de Conteo de lineas var lineCount = new Array(); /** * Agrega una linea de datos a un formulario * @param string div El ID del div objetivo donde se agrega una linea * @param string line El ID del div que contiene la linea a agregar * @param string f Funcion extra para pasarle a los eventos */ function addFormLine(div, line, f) { var f = (f == null) ? "" : f; lineCount[div] = lineCount[div] == null ? 1 : lineCount[div] + 1; var mySelf = div + "_line_" + lineCount[div]; var myNum = lineCount[div]; var divTarget = document.getElementById(div); var divLine = document.getElementById(line).innerHTML; var divTitle = document.getElementById(line).getAttribute('title'); var newDiv = document.createElement('div'); newDiv.className = 'row'; newDiv.setAttribute('id', mySelf); divLine = divLine.replace(/mySelf/g, mySelf); newDiv.innerHTML = divLine; newDiv.innerHTML += "<div class=\"cell\"><img style=\"cursor: pointer;\" src=\"remove.gif\" border=\"0\" onclick=\"removeFormLine(\'" + mySelf + "\'); " + f + "\"></div>"; if (divTitle != null && divTarget.hasChildNodes() == false){ var titles = divTitle.split(","); var newTitle = document.createElement('div'); newTitle.className = 'row'; for (i = 0; i < titles.length; ++i){ var titleSize = titles[i].match(/\(\w+\)/,''); titleSize = titleSize[0].replace(/[\(\)]/g,''); var titleName = titles[i].replace(/\(\w+\)/,''); newTitle.innerHTML += "<div class=\"title\" style=\"width: " + titleSize + "px;\">" + titleName + "</div>"; } divTarget.appendChild(newTitle); divTarget.setAttribute('cab', '1'); } divTarget.appendChild(newDiv); } /** * Elimina una linea de un formulario * @param string div El ID del div que se quiere eliminar */ function removeFormLine(div) { var parentName = div.replace(/_line_\w+/g, ''); var divParent = document.getElementById(parentName); var divTarget = document.getElementById(div); var hasTitle = divParent.getAttribute('cab'); divParent.removeChild(divTarget); if (hasTitle != null && divParent.childNodes.length == 1){ divParent.innerHTML = ""; } }
La funcion primordial es "addFormLine" los demas es usado internamente por esta función. Como podemos ver se piden 3 datos que describo a continuación:
- div: Es el ID del div donde se agregará la nueva linea
- line: Es el ID del div donde se encuentra la "plantilla" a copiar y adjuntar en "div"
- f: [opcional] El nombre de alguna función que se desea ejecutar cuando la linea sea borrada, por ejemplo para recalcular la sumatoria de subtotales
La llamada a la función es muy fácil, solo debemos de seguir las reglas antes mencionadas y con algo parecido a lo siguiente lo tendremos funcionando:
<form method="POST" action=""> <a href="javascript:addFormLine('myDiv', 'myLine');">Agregar Linea +</a><br><br> <div id="myDiv"></div> <br> <input type="submit"> </form>
Veremos que hace referencia a un objeto llamado "myLine", que simplemente es un fragmento de HTML común y corriente, pero con una pequeña diferencia. Revisemos el ejemplo propuesto:
<div id="myLine" class="hide" title="Nombre(200),Categoria(200),Costo(50)"> <div><input type="text" value="" name="nombre[]" maxlength="200" style="width: 200px"></div> <div><select id="list_categorias" name="categoria[]" style="width: 200px"> <option value="0">Seleccione...</option> <option value="1">Viaticos</option> <option value="2">Equipo</option> <option value="3">Servicio</option> <option value="4">Otros</option> </select></div> <div><input type="text" value="" name="costo[]" maxlength="11" style="width: 50px"></div> </div>
Podemos notar que esta "oculto", para ello uso una simple clase de CSS y lo declaro "hidden", de esta forma no se verá en pantalla, también vemos que su ID es efectivamente al que estamos llamando ("myLine") para agregar a nuestro formulario, y por último veremos lo siguiente:
title="Nombre(200),Categoria(200),Costo(50)"
No es mas que una declaración del titulo de las columnas de la tabla, esto quiere decir, que cuando se mande llamar la primera linea se agrega un "header" con los nombres propuestos (Nombre, Categoria y Costo) y un tamaño de ancho en pixeles con el valor que se encuentra entre paréntesis al lado del nombre de columna. Esta propiedad es opcional si no se pone no se dibujan los "titulos".
Pues eso es todo, espero que sea de ayuda y queda abierta la discución y estamos abiertos a las correcciónes y/o adiciones que sean necesarios.
Tengo un ejemplo corriendo junto con su código fuente
Y como siempre, el archivo se encuentra disponible para su descarga a continuación:
| Adjunto | Tamaño |
|---|---|
| formularios_dinamicos_2.zip | 2.05 KB |
![]() |
Es un tema muy interesante que he pensado en otras ocasiones como lo podría resolver, no he hecho pruebas, pero mi idea para el uso de código de barras sería mas o menos así: 1. Un formulario que el post sea manejado por alguna librería ajax, ya sea por POST o por GET. En teoría un lector de Codigo de Barras, manda un numero y seguidamente un enter, ese enter puede ser capturado mediante el "submit" del formulario y enviarlo por ajax al servidor para ser revisado 2. Ya que llega al servidor, se revisa el numero y se regresa la respuesta, si es valido, manda la linea que debe ser agregada (appendChid) a un listado (fomulario) de los productos, en caso contrario, mostrar un div con un mensaje de error temporizado, y quizá con un flash oculto que ejecute un sonido "beeee" de error para alarma sonora. (Esto se puede controlar fácilmente con JavaScript. 3. Una vez terminados los procesos del paso 2 se limpia el "input" del formulario 1 y se le da foco de nuevo, esperando el numero y el enter. Como puedes ver, la idea es interesante y trata de ser lo más transparente al usuario que se pueda. Además el control de todos estos procesos son relativamente fáciles y solo se ocupan 3 o 4 eventos. Por favor cuéntanos como te va, creo que es un tema que le interesará a más de uno. |
![]() |
Un Saludo. inkalawa |
![]() |
Me encantaría poder ayudarte, si tienes algún lugar donde donde estés trabajando tu módulo, pasálo y trataré de ayudarte. Saludos |
![]() |
Hola Nexus...te cuento que ya resolvi el asunto
Lógicamente me toco leer muchisimo y ver muchos ejemplos... te cuento que el tema de Ajax es super interesante y ayuda muchisimo en la construccion de Interfaces Visuales más agradables y 'moviles'. Aqui adjunto 3 archivos en los cuales realicé las modificaciones que necesité pero ojo que doy credito al sitio y la persona que figura como dueño del desarrollo inicial. Un Gran Saludo. Inkalawa PD.Tengo otras preguntas para más adelante ------------- zonas.php ------------- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Consulta Registro con AJAX</title> <!-- referenciamos al archivo ajax.js donde se encuentra nuestra funcion objetoAjax--> <script language="JavaScript" type="text/javascript" src="ajax.js"></script> </head> <body> <p> </p> <div id='TitleForm' style='position:absolute; left:0; top:0; width:750px; height:50px; z-index:1; background-color: #0066CC; layer-background-color: #0066CC; border: 1px none #000000;'> <div align='center'><font color='#FFFFFF' size='+3'><strong>Cargue Cajon Simple</strong></font></div> </div> <p> </p> <!-- En "onsubmit" escribimos la función 'MostrarConsulta' que creamos en javascript, con su parametro que es el archivo que vamos a mostrar, en este caso 'consulta.php'--> <form name="consulta" action="" onsubmit="MostrarConsulta('consulta.php',document.consulta.Txt_Barras.value,document.consulta.Txt_Barras.name); return false"> <!-- construye Form--> <table align='center'> <tr> <td>Zona:</td> <td>Precio:</td> <td>Cliente:</td> </tr> <tr> <td>Descripción Zona: </td> <td colspan='2' align='center' bgcolor='#FFFFFF'> </td> <td>Datos Cliente: </td> </tr> <tr> <td colspan='6' align='center' bgcolor='#FFFF00'><font size='5'> Barras: <input name='Txt_Barras' type='text' id='Txt_Barras' tabindex='1' size='16' maxlength='16' /> </font></td> </tr> <tr bgcolor='#0066CC'> <td colspan='6' align='center'><font color='#FFFFFF' size='3'> DETALLE DE LA ZONA </font></td> </tr> <tr> <td colspan='2' align='center' bgcolor='#00CCFF'></td> <td colspan='2' align='center' bgcolor='#FFFFFF'> </td> <td colspan='2' align='center' bgcolor='#00CC66'> <input type='submit' disabled='disabled' value='Iniciar Cargue' /> </td> </tr> </table> </form> <div id="resultado"></div> </body> </html> ---------- ajax.js ---------- //Desarrollado por Jesus Liñán //ribosomatic.com //Puedes hacer lo que quieras con el código //pero visita la web cuando te acuerdes function objetoAjax(){ var xmlhttp=false; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest!='undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; } function MostrarConsulta(datos,txtsend,txtobj){ divResultado = document.getElementById('resultado'); ajax=objetoAjax(); // ajax.open("GET", datos); ajax.open("GET", "consulta.php?page="+txtsend,true); ajax.onreadystatechange=function() { if (ajax.readyState==1){ //document.getElementById(div).innerHTML = '<img src="../imagenes/ajax-loader2.gif">'; divResultado.innerHTML ="<img src='imagenes/ajax-loader_Loading.gif'>"; } if (ajax.readyState==4) { divResultado.innerHTML = ajax.responseText document.getElementById(txtobj).select(); } } ajax.send(null) } ---------------- consulta.php ---------------- <?php if ($page=="") { echo "<p>Barras: vacio".$page.""; }else{ echo "<p>Barras: ".$page.""; //Configuracion de la conexion a base de datos $Servidor = $DirIp; $bd_host=$Servidor; //$bd_host = "localhost"; $bd_usuario = "xxxx"; $bd_password = "xxxx"; $bd_base = "sin_centro"; $con = mysql_connect($bd_host, $bd_usuario, $bd_password); mysql_select_db($bd_base, $con); //consulta $IdConsulta=mysql_query("SELECT * FROM 25_ingreso_bases where barras=".$page."",$con); $NFilas = mysql_num_rows($IdConsulta); if ($NFilas==0) { echo "<p>Codigo de Barras no EXISTE"; }else{ echo "<p>Numero de Filas: ".$NFilas."</p>\n" ; //Ver informacion echo "<p>ID - CIUDAD - CLIENTE</p> \n"; while($row = mysql_fetch_array($IdConsulta)){ echo "<p>".$row['NumIdInterno']." - ".$row['Barras']."</p> \n"; } } } ?> |
![]() |
Hola Nexus Ante todo Gracias por tu tiempo. |
![]() |
1. Si se puede con la propiedad "background-color" de CSS, es bastante fácil. 2. No se a que te refieres con encapsular, pero si, todos los archivos se pueden reutilizar si sabes como programarlos "extensibles" |
![]() |
en relacion a los formularios dinamico 2.0 |
![]() |
Buena pregunta... me parece algo sumamente complicado ya que tienes que revisar, tanto cuando se agrega, como cuando se borra... vaya, parece que no es tarea fácil. |
![]() |
Esta validacion me funciono. var findInputs = myDiv.getElementsByTagName('input'); //aqui empieza validacion for (var i = 0; i < findInputs.length; i++){ if (findInputs[i].value =='') { alert("ingrese valor"); form_registro_clinico_erh.focus(); return(false); } } chau desde ya gracias Edgar |
![]() |
Por alguién, podria explicarme como puedo extrar los valores de htmlentities, para ingregrar a la tabla de detalle de facturas. gracias |
![]() |
este codigo funciona perfecto en la funcion addline
//pregunto por >=4 por que tengo 2 arreglo con select con tablas(medicamento y unidad) el de medicamento esta en las posiciones pares ejemplo findInputs68[0] findInputs68[2] findInputs68[4] las posiciones impares son las unidades findInputs68[1] findInputs68[3] findInputs68[5] si tiene 3 medicamentos ingresados por eso los for se incrementan en 2.-EL lengh es 6 if (findInputs68.length>=4) { for (var i=0; i<findInputs68.length-2 ; i+=2) { for (var j=i+2; j< findInputs68.length ; j+=2) { if ( findInputs68[i].value== findInputs68[j].value ) { alert("Medicamento Repetido, verifique por Favor"); form_registro_clinico_erh.focus(); } } } } chao espero que a alguien le sirva.Edgar |
![]() |
Muy elegante la forma de validarlo, me parece que lo resolviste con la mejor lógica, muchas gracias por tu ayuda. Saludos |
![]() |
como puedo hacer un autocompletar con un select (una tabla odbc) en los formularios dinamicos.a continuacion el mi codigo en la funcion addline var content = document.getElementById('myDiv'); var divIdName = 'my' + count + 'Div'; var newDiv = document.createElement('div'); newDiv.setAttribute('id', divIdName); <?php $STR_Conex_Aba=odbc_connect($STR_Odbc_Aba,$STR_Login_Aba,$STR_Pass_Aba); $sql = "SELECT codigo,descripcion[1,18] FROM abfbt001 where bodega=2 and estado='AC' ORDER BY codigo ASC"; if (!$STR_Conex_Aba){ exit("A ocurrido un error tratando de conectarse con el origen de datos."); } $results=odbc_exec($STR_Conex_Aba,$sql)or die(exit("Error en odbc_exec")); ?> var sel = document.createElement("SELECT"); sel.setAttribute("size","1"); sel.setAttribute("name","myselect[]" ); <?php while ($rows= odbc_fetch_array($results)) { extract($rows); echo "opcioncur = document.createElement('OPTION');"; echo "opcioncur.innerHTML = '".$descripcion."';"; echo "opcioncur.value = '".$codigo."';"; echo "sel.appendChild(opcioncur);"; } newDiv.appendChild(sel); content.appendChild(newDiv); |
![]() |
Eso no me parece autocompletar, sino llenar de opciones un select, en ese caso te recomiendo que revises de nuevo este artículo y veas la parte de la linea que se agrega, ahí es donde debes llenar tu select, no en el ajavascript. Saludos |
![]() |
la idea es que una vez llenos los select despues de hacer click en agregar linea el usuario digita h y se muestren todos medicamentos que comienzen con h y al digitar la o se muestren por ejemplo las hormonas |
![]() |
Siento comentarte que el alcance de estas funciones para los formularios dinámicos no llegan tan lejos y no tiene un "autocompletar", pero bien podrías hacer uso de una suite Ajax para lograr tu cometido. Te recomiendo DHTML Goodies que es la que uso con frecuencia. Saludos |
![]() |
como estraigo los valores de htmlentities???, ya que no se como recibir los valores agregado en el formulario. Thx advance. |
![]() |
Hola, no es necesario hacer tantos posts. Te explico, el " Despues el " En el ejemplo se podrá ver que por ejemplo:
Es la primera linea del formulario y:
Es la segunda linea. Espero que quede un poco más claro. Saludos |



Primero un Gran Saludo para Nexus.
Estoy de acuerdo con los comentarios de valorar sus aportes al conocimiento.
Entrando en materia....estoy trabajando en un proyecto en donde intervienen unos formularios que deben tomar la informacion, en tiempo real, que procesa el usuario usando un lector de códigos de barras, lo pongo en contexto:
1. el usuario debe elegir unos valores por defecto de unos ComboBox
2. una vez esten estos valores procede a darle: INICIAR en un boton normal.
3. se bloquean los datos seleccionados y se lleva el enfoque(focus) a un TextBox
4. en este TextBox es donde se leen los Códigos de Barras y se determinan las acciones:
a. Consultar la Base de Datos
b. si existe el valor en la BD, entonces limpiar y seguir
b. si NO existe el valor en la BD, entonces mostrar Mensaje y limpiar y enfocar.
............ espero haberme hecho entender, aclaro que no es una tarea y que SI he hecho varias pruebas pero encuentro un error al llamar el mismo formulario con los eventos: OnChange,OnKeyPress, etc.
Agradezco sus valiosos comentarios.
inkalawa