Why do I have an "too much recursion" error when trying to submit () with JavaScript?

2

I'm trying to do a simple submit () through JavaScript but in the console I get an error of "too much recursion" and there the program is slowed down.

I'm trying to validate the clicks within a modal and save the input's clicked into an array, if then the fix meets certain conditions, the submit is done, otherwise an error message will appear for the user.

/* Validar checkboxes clickeados */
var checkboxes = document.querySelectorAll('.single-checkbox');
var clickeados = [];

checkboxes.forEach(elem => {
    elem.addEventListener('change', (event) => {
        event.stopPropagation();
        if(elem.checked) {
           if(!clickeados.includes(elem)){
                   clickeados.push(elem);
                   console.log(clickeados);
           }
        }
        else{
            if(clickeados.includes(elem)){
                   clickeados.pop(elem);
                   console.log(clickeados);
            }
        }
    });
});

/* Validar cuantos gustos fueron seleccionados antes de hacer el submit */
$('#vasitoForm').on('submit', (event) =>
    if(clickeados.length == 0){
        event.preventDefault();
        document.getElementById("errorGustos").innerHTML = "Debe seleccionar por lo menos un gusto";
    }
    else if(clickeados.length > 0 && clickeados.length < 3){
        $('#vasitoForm').submit();
    }
});

The preventDefault () is fine if nothing is clicked and it shows the error message without redirecting, but when having input's clicked and doing the submit () the console message "too much recursion"!

The HTML is as follows:

<!-- Modal -->
<div id="vasoModal" class="modal">
    <div class="modal-content">
        <h4 class="modal-title">Vasito</h4>
        <h6>Seleccione hasta dos gustos</h6>
        <form th:action="@{/pedido}" id="vasitoForm" method="post">
            <table class="tabla">
                    <tr th:each="gusto : ${gustos}">
                        <td class="flavour" th:text="${gusto.nombre}"></td>
                        <td><input class="single-checkbox" type="checkbox" th:value="${gusto.id}"/></td>
                    </tr>
            </table>
            <p id="errorGustos"></p>
            <button type="submit" class="btn-submit">Enviar Pedido</button>
        </form>
    </div>
</div>

Any idea why this happens and how can it be solved?

    
asked by Nacho Zve De La Torre 26.11.2018 в 15:17
source

1 answer

8

I'll analyze the code so you can see the problem:

This code is equivalent to yours, but we give a name to the function to execute:

// Pongamos un nombre a la función
const callbackFunction = (event) =>
    if(clickeados.length == 0){
        event.preventDefault();
        document.getElementById("errorGustos").innerHTML = "Debe seleccionar por lo menos un gusto";
    }
    else if(clickeados.length > 0 && clickeados.length < 3){
        $('#vasitoForm').submit(); // ESTE ES EL PROBLEMA
    }
}

$('#vasitoForm').on('submit', callbackFunction);

Therefore:

  • Assign to event submit the execution of callbackFunction .
  • The user makes a submit
  • The submit event has occurred! It is called callbackFunction .
  • The callbackFunction function cancels the current event with event.preventDefault(); .
  • The function callbackFunction verifies that everything is fine and the submit can be done, therefore it calls form.submit() , which throws the event submit . GO TO 3
  • You enter a loop in which the submit event is stopped and a new event is thrown the same. It is an indirect recursion loop with no base case, then it never ends and the JS interpreter ends without memory, causing the failure.

    The solution is the following:

    const callbackFunction = (event) =>
      if(clickeados.length > 0 && clickeados.length < 3) {
         return; // todo va bien, dejamos que todo siga, hemos terminado
      }
      // algo no está bien, cancelamos el evento
      event.preventDefault();
      document.getElementById("errorGustos").innerHTML = "Debe seleccionar por lo menos un gusto";
    
    }
    
    $('#vasitoForm').on('submit', callbackFunction);
    
        
    answered by 26.11.2018 / 16:25
    source