Search code examples
javascriptajaxpromiseonsubmit

JS AJAX: promise dependant submit always submitted


Finally, I managed to do this:

function validar(dato_a_validar, url, secc)
{
        var datastr = "secc=" + secc + "&dato=" + dato_a_validar;
        return new Promise(function(resolve, reject) {
                $.ajax({
                        type:'GET',
                        url:url,
                        data:datastr,
                        success:function(response) { resolve(response); },
                        error:function(response) { reject(response); }
                });
        });
}

async function check_submit()
{
        init(); // sets some global variables
        errores_personal_cnt = 0; // error counter

        var dni_ctl = document.getElementById("frm_funcionario_dni");
        var dni = dni_ctl.value;

        dni_ctl.style.borderColor = "black";
        dni_ctl.style.backgroundColor = "none";


        const estado = await validar(dni, url_validacion, "dni")
                .then(salida => estadoValidacion(dni_ctl, salida)) // estadoValidacion() sets some colour and form control title
                .catch(error => estadoValidacion(dni_ctl, "error"));
        $.when(estado).done(console.log("Errores: " + errores_personal_cnt));
        return false; // this is set for tests purposes, but is always ignored.
}

On the onsubmit event, async function check_submit() is called. validar(...) function returns a promise (I guess), and with .then() and .catch() y handle both results. However, even when there are wrong fields, the form is submitted.

I think the reason the form is always submitted is because I have some wrong code somewhere but I can't figure out where.

Thanks!


Solution

  • Explaining with an example suppose I have a form that I validate using promised based approach. Suppose validar() is a function that does some validation and takes 3 secs (I have many fields you know!). But when used like this it fails! see in below comments as to why is so.

    <form action="google.com" id="frm">
      <input id="txt">
      <button type="submit">submit</button>
    </form>
    
    <script>
      document.getElementById('frm').onsubmit = () => {
        var check = check_submit();
        console.log(check); //Promise {<pending>}
        console.log(check ? true : false) // which is evaluates to true! (check ? true : false) <-- true
        //So browser proceeds with form's default behavior which is to submit on google.com
      }
    
      function validar() {
        return new Promise(function(resolve, reject) {
          setTimeout(() => resolve(false), 3000)
        });
      }
    
      async function check_submit() {
        var result = validar(); // <-- this line NEVER WAITS for the promise of validar to get resolve() 'ed 
        // instead its current value which is Promise {<pending>}  is used immediatly and RETURNED!
        return result;
      }
    </script>

    How to make it work then? It's simple just stop the default behavior by returning false in onsubmit unconditionally and manually submit form(if valid) when the promise value gets resolved

    <form action="google.com" id="frm">
      <input id="txt">
      <button type="submit">submit</button>
    </form>
    
    <script>
      document.getElementById('frm').onsubmit = () => {
        check_submit(); //<-- will handle our form submission business
        return false; //unconditional
      }
    
      function validar() {
        return new Promise(function(resolve, reject) {
          setTimeout(() => resolve(false), 3000)
        });
      }
    
      async function check_submit() {
        var result = await validar(); //<-- this line NOW WAITS (due to await) for the promise of validar to get resolve() 'ed
        if (result) {
          alert('submitting form as validar returned true')
          document.getElementById('frm').submit(); // submit manully as promise'd value returned true
        } else
          alert('meh')
      }
    </script>