Como reenviar form após devidas validações e uso do event.preventDefault()?

Pessoal, bom dia! Como eu faria para enviar um form via js após chamar o event.preventDefault() para abortar a submissão do mesmo?

Eu fiz isso para validar os campos com uma função checkInput(), de forma q dentro do listener que que pega o submit só tem a chamada para a e.preventDefault() e depois para a checkInput().

Eu até tentei pôr um e.target.submit() após essas duas chamadas, mas isso resultou em um comportamento não esperado, enviando o forma sem validar corretamente os campos.

Quem puder me ajudar aí, é só dar um toque, o tema mesmo está logo na pergunta de abertura, os parágrafos seguintes são apenas para explicar o contexto. Segue abaixo o código JS citado:

const form = document.querySelector('#form');
const username = document.querySelector('#username');
const email = document.querySelector('#email');
const password = document.querySelector('#password');
const password2 = document.querySelector('#password2');

form.addEventListener('submit', e => {
    e.preventDefault();
    const status = checkInputs();

    if (status) {
        e.target.submit();
    }
});

function checkInputs() {
    // get the values from the inputs
    const usernameValue = username.value.trim();
    const emailValue = email.value.trim();
    const passwordValue = password.value.trim();
    const passwordCheck = password2.value.trim();

    if (usernameValue === '') {
        setErrorFor(username, "Username cannot be blank");
    } else {
        setSuccessFor(username);
    }
    if (emailValue === '') {
        setErrorFor(email, "Email cannot be blank");
    } else if(!isEmail(emailValue)) {
        setErrorFor(email, "Email is not valid");
    } else {
        setSuccessFor(email);
    }

    if (passwordValue === '') {
        setErrorFor(password, "Password cannot be blank");
    } else {
        setSuccessFor(password);
    }

    if (passwordCheck === '') {
        setErrorFor(password2, "Password check cannot be blank");
    } else if(passwordValue !== passwordCheck) {
        setErrorFor(password2, "Passwords does not match");
    } else {
        setSuccessFor(password2);
    }

    return true;
}

function setErrorFor(input, message) {
    const formGroup = input.parentElement; // .form-group
    const small = formGroup.querySelector('small');

    // add error message inside small
    small.innerText = message;

    // add error class
    formGroup.className = 'form-group error';
}

function setSuccessFor(input) {
    const formGroup = input.parentElement; // .form-group
    formGroup.className = 'form-group success';
}

function isEmail(email) {
    return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(email);
} 

O HTML do exemplo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS Form Validation</title>
    <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css">
    <link rel="stylesheet" href="/css/style.css">
</head>
<body>
    <div class="container">
        <div class="header">
            <h2>Create Account</h2>
        </div>
        <form class="form" id="form" method="GET" action="#">
            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username">
                <i class="fas fa-check-circle"></i>
                <i class="fas fa-exclamation-circle"></i>
                <small>Error message</small>
            </div>

            <div class="form-group">
                <label for="email">Email</label>
                <input type="email" id="email">
                <i class="fas fa-check-circle"></i>
                <i class="fas fa-exclamation-circle"></i>
                <small>Error message</small>
            </div>

            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password">
                <i class="fas fa-check-circle"></i>
                <i class="fas fa-exclamation-circle"></i>
                <small>Error message</small>
            </div>

            <div class="form-group">
                <label for="password2">Password check</label>
                <input type="password" id="password2">
                <i class="fas fa-check-circle"></i>
                <i class="fas fa-exclamation-circle"></i>
                <small>Error message</small>
            </div>

            <button type="submit">Submit</button>
        </form>
    </div>

    <script src="/js/script.js"></script>
</body>
</html>

Aguardo sugestões, valeu!

Por favor, evite mandar imagem de código. Sempre copie e cole-o para facilitar a ajuda.

Para submeter o form, vc tentou fazer?

form.submit();

E esse e.target.submit() não foi? Fiz um teste aqui e ele realiza a submissão (a página é até atualizada).

@Lucas_Camara, eu editei o post para conter os códigos e assim ficar mais fácil obter ajuda.

Olha, o form é até submetido, mas sem dar ao usuário a opção de preencher os dados corretamente. Por exemplo ao carregar a página e eu tentar submeter o form com os campos vazios, rapidamente exibe os erros em fração de segundos e envia o form, não deixando o usuário preencher ou informar corretamente os dados.

1 curtida

Vlw!


Entendi. Então talvez seja o caso de colocar o submit num condição:

SE (form for válido) {
    submete o form
} SENAO {
    Apresenta os erros do formulário para o usuário
}

EDIT

Caramba véi, postei minha resposta e soh depois reparei no seu código, q vc está fazendo exatamente o que respondi. Falta de atenção minha de não ter visto sua edição antes de responder.

Mas então, mesmo com a verificação:

if (status) {
        e.target.submit();
    }

o form não é submetido?

Agora foi, eu alterei a função checkInputs() para conter um flag booleano setado como true, e em cada validação q nao passasse ele setasse esse valor para false, ao fim da função retornei esse flag. E no bloco do listerner testei o retorno de checkInputs, se true ele envia o form: funcionou exatamente como eu desejava.

Código final:

const form = document.querySelector('#form');

form.addEventListener('submit', e => {
    e.preventDefault();

    let username = document.querySelector('#username');
    let email = document.querySelector('#email');
    let password = document.querySelector('#password');
    let password2 = document.querySelector('#password2');

    if (checkInputs()) {
        e.target.submit();
    }
});

function checkInputs() {
    // flag to submit form
    let status = true;
    
    // get the values from the inputs
    let usernameValue = username.value.trim();
    let emailValue = email.value.trim();
    let passwordValue = password.value.trim();
    let passwordCheck = password2.value.trim();

    if (usernameValue === '') {
        setErrorFor(username, "Username cannot be blank");
        status = false;
    } else {
        setSuccessFor(username);
    }

    if (emailValue === '') {
        setErrorFor(email, "Email cannot be blank");
        status = false;
    } else if(!isEmail(emailValue)) {
        setErrorFor(email, "Email is not valid");
        status = false;
    } else {
        setSuccessFor(email);
    }

    if (passwordValue === '') {
        setErrorFor(password, "Password cannot be blank");
        status = false;
    } else {
        setSuccessFor(password);
    }

    if (passwordCheck === '') {
        setErrorFor(password2, "Password check cannot be blank");
        status = false;
    } else if(passwordValue !== passwordCheck) {
        setErrorFor(password2, "Passwords does not match");
        status = false;
    } else {
        setSuccessFor(password2);
    }

    return status;
}

function setErrorFor(input, message) {
    const formGroup = input.parentElement; // .form-group
    const small = formGroup.querySelector('small');

    // add error message inside small
    small.innerText = message;

    // add error class
    formGroup.className = 'form-group error';
}

function setSuccessFor(input) {
    const formGroup = input.parentElement; // .form-group
    formGroup.className = 'form-group success';
}

function isEmail(email) {
    return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(email);
}

Valeu muito pela a sua atenção, mano!

1 curtida

Onde marco o tópico como SOLUCIONADO/RESOLVIDO?

Vai nos três pontos ao lado de responder. Lá vai ter um botão para marcar com solução (Mark as solution).

image

1 curtida