Foros del Web » Programando para Internet » Javascript »

Caso interesante con validación de formularios

Estas en el tema de Caso interesante con validación de formularios en el foro de Javascript en Foros del Web. Digamos que estamos validando un formulario con Javascript y la API HTML5 para formularios, validityState, checkValidity etc... yo lo estoy intentando pero quiero llevarlo un ...
  #1 (permalink)  
Antiguo 15/06/2014, 13:54
Avatar de nanotime  
Fecha de Ingreso: noviembre-2011
Ubicación: Cd. Guayana
Mensajes: 145
Antigüedad: 12 años, 5 meses
Puntos: 6
Pregunta Caso interesante con validación de formularios

Digamos que estamos validando un formulario con Javascript y la API HTML5 para formularios, validityState, checkValidity etc... yo lo estoy intentando pero quiero llevarlo un pasito mas allá que simplemente validar en tiempo real cambiándole los colores a un input no válido, quiero agregar en ese mismo tiempo real alertas con cajas de mensajes (puede que no lo haga sino que sea mas diferido, cuando haga click en enviar, lo del tiempo real no es importante).

La cosa es que lo estoy haciendo en puro vanilla JS, primero. Luego usaré Jquery y otras librerías puesto que con esto quiero sacar unos benchs a ver cual es mas eficiente (vanilla, obviamente) y cuantas ops/sec hace cada script.

En fin mi duda está en como hacer para ir apareciendo los mensajes correspondientes en el input errado. Lo primero y principal es, claro está, el trigger del evento:

Código Javascript:
Ver original
  1. document.welcome.addEventListener('invalid', validate, true);

La forma lógica de trabajarlo sería así:

Código Javascript:
Ver original
  1. function validate(e) {
  2.     var elem = e.target;
  3.  
  4.     if(elem.validity.valid){
  5.       .... foo bar
  6.     }
  7. }

He estado investigando y si bien sé que target es un atributo del evento que seleccionará el elemento (input en este caso) que esté fallando, no se como compararlo ya que no se si devuelve una referencia.

Me explico un poco más:

Lo que realmente quiero es poder comprobar cual es el elemento que está fallando para activar el div correspondiente debajo del input. Hay varias maneras de tener dispuestas las cajas, puedo o tener un div listo con la clase y mantenerle el display: none y cambiarle luego los atributos, cambiarle la clase o hasta crear un nuevo elemento y ponerlo al final, la cosa es saber cual input falla para poner debajo de la caja con el mensaje.

So, si tengo este html:

Código HTML:
Ver original
  1. <div class="fields">
  2.         <div class="field">
  3.           <label for="fname">Name:</label>
  4.           <input type="text" name="fname" placeholder="your name here" required>
  5.           <div id="name" class="flash"></div>
  6.         </div>

necesito entonces saber si mi input[name="fname"] es el target que falla para poner a funcionar el div#name.flash por poner un ejemplo.

¿Como hago la comparación? ¿Puedo extraer del elemento target algo así como su campo name? ¿Puedo hacer una simple comparación entre element == document.querySelector("input[name='fname'] ... ")? Ahí es donde radica mi duda

edito:

Pues hasta ahora investigando se supone que puedo acceder a los elementos del DOMTree en un evento como cualquier otro elemento (en teoría), codee este script básico a ver que tal va, este es:

Código Javascript:
Ver original
  1. function init() {
  2.   document.welcome.addEventListener('invalid', validate, true);
  3.   document.querySelector('.button-send').addEventListener('click', send, false);
  4. }
  5.  
  6. function validate(e) {
  7.   var el = e.target;
  8.  
  9.   var elem = {
  10.     name : document.querySelector("input[name='fname']"),
  11.     lname: document.querySelector("input[name='lname']"),
  12.     age  : document.querySelector("input[name='age']"),
  13.     mail : document.querySelector("input[name='mail']")
  14.   };
  15.  
  16.   var sel = {
  17.     name : document.getElementById('name-err'),
  18.     lname: document.getElementById('lname-err'),
  19.     age  : document.getElementById('age-err'),
  20.     mail : document.getElementById('mail-err')
  21.   };
  22.  
  23.   if(el.validity.valueMissing){
  24.     if(el.name == elem.name.name) {
  25.       sel.name.classList.add('flash');
  26.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  27.     } else if(el.name == elem.lname.name){
  28.       sel.lname.classList.add('flash');
  29.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  30.     } else if(el.name == elem.age.name){
  31.       sel.age.classList.add('flash');
  32.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  33.     } else {
  34.       sel.mail.classList.add('flash');
  35.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  36.     }
  37.   }
  38.   else if(el.validity.typeMissMatch){
  39.     if(el.name == elem.main.name)
  40.       sel.mail.classList.add('flash');
  41.       sel.mail.innerHTML = "<p>Please enter a valid mail<p>";
  42.   }
  43.   else if(el.validity.patternMissMatch){
  44.     if(el.name == elem.name.name) {
  45.       sel.name.classList.add('flash');
  46.       sel.name.innerHTML = "<p>Please, insert just text<p>";
  47.     } else if(el.name == elem.lname.name){
  48.       sel.lname.classList.add('flash');
  49.       sel.name.innerHTML = "<p>Please, insert just text<p>";
  50.     } else if(el.name == elem.age.name){
  51.       sel.age.classList.add('flash');
  52.       sel.name.innerHTML = "<p>Sure is your age?<p>";
  53.     }
  54.   } else {
  55.     console.log('alo?');
  56.   }
  57. }
  58.  
  59. function send(){
  60.   var valid = document.welcome.checkValidity();
  61.   if(valid)
  62.     document.welcome.submit();
  63. }
  64.  
  65. window.addEventListener('load', init(), false);

Solo hay una cuestión, me dice "TypeError: document.welcome is undefined"... lo raro (y divertido) es que si accesa a document.welcome desde la consola JS de firefox/chrome sin líos, mas no desde el script ._____.

Aún no he podido probarlo, no encuentro la razón de ese error.

A cualquier idea, opinión y respuesta ... muchas gracias!

Última edición por nanotime; 15/06/2014 a las 15:17
  #2 (permalink)  
Antiguo 15/06/2014, 15:50
Avatar de Italico76  
Fecha de Ingreso: abril-2007
Mensajes: 3.303
Antigüedad: 17 años
Puntos: 292
Respuesta: Caso interesante con validación de formularios

Bueno... agregando el <FORM> ya al menos desaparece ese error:

Código Javascript:
Ver original
  1. <form name="welcome">
  2. <div class="fields">
  3.         <div class="field">
  4.           <label for="fname">Name:</label>
  5.           <input type="text" name="fname" placeholder="your name here" required>
  6.           <div id="name" class="flash"></div>
  7.         </div>
  8. </form>
__________________
Salu2!
  #3 (permalink)  
Antiguo 15/06/2014, 17:58
Avatar de nanotime  
Fecha de Ingreso: noviembre-2011
Ubicación: Cd. Guayana
Mensajes: 145
Antigüedad: 12 años, 5 meses
Puntos: 6
Respuesta: Caso interesante con validación de formularios

Cita:
Iniciado por Italico76 Ver Mensaje
Bueno... agregando el <FORM> ya al menos desaparece ese error:

Código Javascript:
Ver original
  1. <form name="welcome">
  2. <div class="fields">
  3.         <div class="field">
  4.           <label for="fname">Name:</label>
  5.           <input type="text" name="fname" placeholder="your name here" required>
  6.           <div id="name" class="flash"></div>
  7.         </div>
  8. </form>
de hecho, el form existe, solo que no lo copie
  #4 (permalink)  
Antiguo 15/06/2014, 18:31
Avatar de Italico76  
Fecha de Ingreso: abril-2007
Mensajes: 3.303
Antigüedad: 17 años
Puntos: 292
Respuesta: Caso interesante con validación de formularios

Cita:
Iniciado por nanotime Ver Mensaje
de hecho, el form existe, solo que no lo copie
Y por que no copias completo el documento incluidas las llamadas a librerias asi nos ahorramos en trabajito de completarlo para depurar el script ?
__________________
Salu2!
  #5 (permalink)  
Antiguo 15/06/2014, 18:50
Avatar de nanotime  
Fecha de Ingreso: noviembre-2011
Ubicación: Cd. Guayana
Mensajes: 145
Antigüedad: 12 años, 5 meses
Puntos: 6
Respuesta: Caso interesante con validación de formularios

Pues hice un par de cambios en el JS y dejo entonces el html:

Código HTML:
Ver original
  1. <!DOCTYPE html>
  2.   <head>
  3.     <meta charset="utf-8">
  4.     <title>Webform</title>
  5.     <link rel="stylesheet" href="css/style.css">
  6.     <script src="js/main.js"></script>
  7.   </head>
  8.   <body>
  9.     <header>
  10.       <h2>Wellcome!</h2>
  11.     </header>
  12.     <section class="form-wrapper">
  13.       <form name="welcome" method="post">
  14.         <div class="fields">
  15.           <div class="field">
  16.             <label for="fname">Name:</label>
  17.             <input type="text" name="fname" placeholder="your name here" pattern="[A-Za-z]" required>
  18.             <div id="name-err"></div>
  19.           </div>
  20.           <div class="field">
  21.             <label for="lname">Last name:</label>
  22.             <input type="text" name="lname" placeholder="your lastname here" pattern="[A-Za-z]" required>
  23.             <div id="lname-err"></div>
  24.           </div>
  25.           <div class="field">
  26.             <label for="age">Age:</label>
  27.             <input type="text" name="age" placeholder="your age here" pattern="[0-9]">
  28.             <div id="age-err"></div>
  29.           </div>
  30.           <div class="field">
  31.             <label for="mail">Email:</label>
  32.             <input type="text" name="email" placeholder="[email protected]" required>
  33.             <div id="mail-err"></div>
  34.           </div>
  35.           <div class="radios"><span>Sex:</span>
  36.             <input type="radio" name="male" value="male"><span>Male</span>
  37.             <input type="radio" name="female" value="female"><span>Female</span>
  38.           </div>
  39.           <div class="text">
  40.             <textarea name="message"></textarea>
  41.           </div>
  42.           <div class="button-wrapper">
  43.             <input type="button" name="send" value="Send" class="button-send">
  44.           </div>
  45.         </div>
  46.       </form>
  47.     </section>
  48.   </body>
  49. </html>

Ahora, el JS:

Código Javascript:
Ver original
  1. function init() {
  2.   document.welcome.addEventListener('invalid', validate, true);
  3.   document.querySelector('.button-send').addEventListener('click', send, false);
  4. }
  5.  
  6. function validate(e) {
  7.   var el = e.target;
  8.  
  9.   var elem = {
  10.     name : document.querySelector("input[name='fname']"),
  11.     lname: document.querySelector("input[name='lname']"),
  12.     age  : document.querySelector("input[name='age']"),
  13.     mail : document.querySelector("input[name='mail']")
  14.   };
  15.  
  16.   var sel = {
  17.     name : document.getElementById('name-err'),
  18.     lname: document.getElementById('lname-err'),
  19.     age  : document.getElementById('age-err'),
  20.     mail : document.getElementById('mail-err')
  21.   };
  22.  
  23.   if(el.validity.valueMissing){
  24.     if(el.name == elem.name.name) {
  25.       sel.name.classList.add('flash');
  26.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  27.     } else if(el.name == elem.lname.name){
  28.       sel.lname.classList.add('flash');
  29.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  30.     } else if(el.name == elem.age.name){
  31.       sel.age.classList.add('flash');
  32.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  33.     } else {
  34.       sel.mail.classList.add('flash');
  35.       sel.name.innerHTML = "<p>Please fill the empty field<p>";
  36.     }
  37.   }
  38.   else if(el.validity.typeMissMatch){
  39.     if(el.name == elem.main.name)
  40.       sel.mail.classList.add('flash');
  41.       sel.mail.innerHTML = "<p>Please enter a valid mail<p>";
  42.   }
  43.   else if(el.validity.patternMissMatch){
  44.     if(el.name == elem.name.name) {
  45.       sel.name.classList.add('flash');
  46.       sel.name.innerHTML = "<p>Please, insert just text<p>";
  47.     } else if(el.name == elem.lname.name){
  48.       sel.lname.classList.add('flash');
  49.       sel.name.innerHTML = "<p>Please, insert just text<p>";
  50.     } else if(el.name == elem.age.name){
  51.       sel.age.classList.add('flash');
  52.       sel.name.innerHTML = "<p>Sure is your age?<p>";
  53.     }
  54.   } else {
  55.     console.log('Algo está mal .... ');
  56.     console.log(el);
  57.   }
  58. }
  59.  
  60. function send(){
  61.   var valid = document.welcome.checkValidity();
  62.   if(valid){
  63.     document.welcome.submit();
  64.   } else {
  65.     console.log('nooope');
  66.   };
  67. }
  68.  
  69. window.addEventListener('load', init, false);

Bien, el tema con el document.welcome era que en el evento de carga que inicializaba todo tenía mal referenciada la clase init... todo listo por ese lado.

Hice un par de logs tontos para saber si se saltaba los condicionales y, en efecto, se los salta...

De hecho al interactuar con los campos no pasa gran cosa, de hecho no pasa nada, no muestra los mensajes no cambia en absolutamente nada (cosa que en teoría debería ocurrir a medida que te vas equivocando en los campos).

Si trato de enviar el formulario sin llenar los cambios, efectivamente me dispara el log que le puse. Si relleno los campos mal, me lanza los logs (menos el de email...) y luego, obviamente el 'nooope' tonto de pruebas.

En fin, al menos ya comprobé que las referencias para hacer las comparaciones son correctas, logeando el.name me devuelve el valor de name y así... ¿Qué está mal entonces en el script? Es mi pregunta ahora

Edito:

Ah! Se me olvidaba poner los logs, claro
Código Javascript:
Ver original
  1. "Algo está mal .... "
  2. <input type="text" required="" pattern="[A-Za-z]" placeholder="your name here" name="fname">
  3. "Algo está mal .... "
  4. <input type="text" required="" pattern="[A-Za-z]" placeholder="your lastname here" name="lname">
  5. "Algo está mal .... "
  6. <input type="text" pattern="[0-9]" placeholder="your age here" name="age">
  7. "nooope"
  #6 (permalink)  
Antiguo 17/06/2014, 19:48
Avatar de nanotime  
Fecha de Ingreso: noviembre-2011
Ubicación: Cd. Guayana
Mensajes: 145
Antigüedad: 12 años, 5 meses
Puntos: 6
Respuesta: Caso interesante con validación de formularios

Le hice un lifting al código y traté de hacerlo bastaaaaaaaante mas sencillo, pero sigue sin funcionar del todo

Código Javascript:
Ver original
  1. function init () {
  2.   document.welcome.addEventListener('valid', watch, true);
  3.   document.querySelector('.button-send').addEventListener('click', send, false);
  4. }
  5.  
  6. function watch (e) {
  7.   var el = e.target;
  8.   var errMsj = document.getElementById('err-msj');
  9.  
  10.   if (el.validity.valid) {
  11.     console.log('Good');
  12.   } else {
  13.     console.log('Warning');
  14.   }
  15.  
  16. }
  17.  
  18. function send () {
  19.  
  20.   var name     = document.querySelector("input[name='fname']"),
  21.       lname    = document.querySelector("input[name='lname']"),
  22.       age      = document.querySelector("input[name='age']"),
  23.       mail     = document.querySelector("input[name='email']"),
  24.       valid    = document.welcome.checkValidity(),
  25.       errMsj   = document.getElementById('err-msj');
  26.    
  27.   if (valid) {
  28.     document.welcome.submit();
  29.   }
  30.   else {
  31.     if (name.validity.valueMissing || lname.validity.valueMissing || age.validity.valueMissing || mail.validity.valueMissing){
  32.       console.log('missing value');
  33.     } else if (name.validity.patternMissMatch || lname.validity.patternMissMatch || age.validity.patternMissMatch){
  34.       console.log('missing pattern');
  35.     } else {
  36.       if ((mail.validity.typeMissMatch)) {
  37.         console.log('type Missing');
  38.       };
  39.     }
  40.   }
  41. }
  42.  
  43. window.addEventListener('load', init, false);

Código HTML:
Ver original
  1. <!DOCTYPE html>
  2.   <head>
  3.     <meta charset="utf-8">
  4.     <title>Webform</title>
  5.     <link rel="stylesheet" href="css/style.css">
  6.     <script src="js/main.js"></script>
  7.   </head>
  8.   <body>
  9.     <header>
  10.       <h2>Wellcome!</h2>
  11.     </header>
  12.     <section class="form-wrapper">
  13.       <div id="err-msj"></div>
  14.       <form name="welcome" method="post">
  15.         <div class="fields">
  16.           <div class="field">
  17.             <label for="fname">Name:</label>
  18.             <input type="text" name="fname" placeholder="your name here" pattern="[A-Za-z]" required>
  19.           </div>
  20.           <div class="field">
  21.             <label for="lname">Last name:</label>
  22.             <input type="text" name="lname" placeholder="your lastname here" pattern="[A-Za-z]" required>
  23.           </div>
  24.           <div class="field">
  25.             <label for="age">Age:</label>
  26.             <input type="text" name="age" placeholder="your age here" pattern="[0-9]">
  27.           </div>
  28.           <div class="field">
  29.             <label for="mail">Email:</label>
  30.             <input type="text" name="email" placeholder="[email protected]" required>
  31.           </div>
  32.           <div class="radios"><span>Sex:</span>
  33.             <input type="radio" name="male" value="male"><span>Male</span>
  34.             <input type="radio" name="female" value="female"><span>Female</span>
  35.           </div>
  36.           <div class="text">
  37.             <textarea name="message"></textarea>
  38.           </div>
  39.           <div class="button-wrapper">
  40.             <input type="button" name="send" value="Send" class="button-send">
  41.           </div>
  42.         </div>
  43.       </form>
  44.     </section>
  45.   </body>
  46. </html>

Acá el cambio es que en vez de volverme loco tratando de disparar un aviso distinto por cada error en forma de caja, lo hago (de forma simulada con logs, por los momentos) con una sola caja que avisa que hay errores en las casillas marcadas (en este caso, lo hago con la pseudo clase :invalid de css) ... o bueno, se supone que debería ir lanzando un log a medida que se equivoca un campo, cosa que no pasa en la función watch.

Respecto a la función send() pues hay un comportamiento extraño. Se supone que cuando se hace click en el botón para enviar el formulario, se activa el condicional que evalúa: si el formulario es válido, envíalo, sino lanza alguna de estas excepciones (los if anidados).

Nada de esto pasa, el único evento que se dispara es si hay un campo vacío, mas allá de eso no se evalúa nada a menos que cambie el tipo de botón button por submit y ahí más o menos empieza a validar, pero sigue sin disparar otros eventos, me dice siempre el mismo log de "value is missing" aunque haya un patternMissMatch. Además, siempre me muestra las cajas de comentarios feas y no hay manera de sacarlas.

Al parecer validar del lado del cliente con la API HTML5 no es tan simple

Etiquetas: formulario, formularios, funcion, html, input, js, select
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:46.