Acionando a validação do formulário HTML5

97

Eu tenho um formulário com vários conjuntos de campos diferentes. Eu tenho algum Javascript que exibe os conjuntos de campos para os usuários, um de cada vez. Para navegadores que oferecem suporte à validação de HTML5, adoraria fazer uso dele. No entanto, preciso fazer isso nos meus termos. Estou usando JQuery.

Quando um usuário clica em um link JS para passar para o próximo fieldset, preciso que a validação aconteça no fieldset atual e impeça o usuário de seguir em frente se houver problemas.

Idealmente, conforme o usuário perde o foco em um elemento, a validação ocorrerá.

Atualmente tem novalidate indo e usando Javascript. Prefere usar o método nativo. :)

Desenhou
fonte

Respostas:

60

Você não pode acionar a IU de validação nativa, mas pode facilmente aproveitar as vantagens da API de validação em elementos de entrada arbitrários:

$('input').blur(function(event) {
    event.target.checkValidity();
}).bind('invalid', function(event) {
    setTimeout(function() { $(event.target).focus();}, 50);
});

O primeiro evento é disparado checkValidityem cada elemento de entrada assim que perde o foco. Se o elemento for invalid, o evento correspondente será disparado e capturado pelo segundo manipulador de eventos. Este define o foco de volta para o elemento, mas isso pode ser muito chato, suponho que você tenha uma solução melhor para notificar sobre os erros. Aqui está um exemplo funcional do meu código acima .

robertc
fonte
20
Frase de ouro "Você não pode acionar a IU de validação nativa" . No meu caso (truques JS personalizados + validação de html5 do navegador + dicas de IU), não tive escolha a não ser usar o botão de envio oculto no final para obter os dois
lukmdo
22
Se o seu formulário não tiver um botão de envio, você pode falsificar um:$('<input type="submit">').hide().appendTo($myForm).click().remove();
philfreo
1
@philfreo Não form.submit()funcionaria bem? Ou o HTML5 exige um botão de envio para validação agora?
Mattisdada
@Mattisdada Calling .submit()não funciona para mim. A solução de @philfreo funciona. Hmm.
Zero3
129

TL; DR: Não se preocupa com navegadores antigos? Use form.reportValidity().

Precisa de suporte para navegador legado? Leia.


Na verdade, é possível acionar a validação manualmente.

Vou usar JavaScript simples em minha resposta para melhorar a capacidade de reutilização, não é necessário jQuery.


Suponha o seguinte formulário HTML:

<form>
  <input required>
  <button type="button">Trigger validation</button>
</form>

E vamos pegar nossos elementos de IU em JavaScript:

var form = document.querySelector('form')
var triggerButton = document.querySelector('button')

Não precisa de suporte para navegadores legados como o Internet Explorer? Isto é para você.

Todos os navegadores modernos suportam o reportValidity()método em formelementos.

triggerButton.onclick = function () {
    form.reportValidity()
}

É isso, terminamos. Além disso, aqui está um CodePen simples usando essa abordagem.


Abordagem para navegadores mais antigos

Abaixo está uma explicação detalhada de como reportValidity()pode ser emulado em navegadores mais antigos.

No entanto, você não precisa copiar e colar esses blocos de código em seu projeto - há um ponyfill / polyfill prontamente disponível para você.

Onde reportValidity()não é compatível, precisamos enganar um pouco o navegador. Então o que vamos fazer?

  1. Verifique a validade do formulário ligando para form.checkValidity(). Isso nos dirá se o formulário é válido, mas não mostra a IU de validação.
  2. Se o formulário for inválido, criamos um botão de envio temporário e acionamos um clique nele. Uma vez que o formulário não é válido, nós sabemos que não vai realmente apresentar, no entanto, ele irá mostrar dicas de validação para o usuário. Removeremos o botão de envio temporário imediatamente, para que ele nunca fique visível para o usuário.
  3. Se o formulário for válido, não precisamos interferir em nada e deixar o usuário prosseguir.

Em código:

triggerButton.onclick = function () {
  // Form is invalid!
  if (!form.checkValidity()) {
    // Create the temporary button, click and remove it
    var tmpSubmit = document.createElement('button')
    form.appendChild(tmpSubmit)
    tmpSubmit.click()
    form.removeChild(tmpSubmit)

  } else {
    // Form is valid, let the user proceed or do whatever we need to
  }
}

Este código funcionará em praticamente qualquer navegador comum (eu testei com sucesso até o IE11).

Aqui está um exemplo de CodePen funcional.

Loilo
fonte
22

Em certa medida, você PODE triggervalidar o formulário HTML5 e mostrar dicas ao usuário sem enviar o formulário!

Dois botões, um para validar, um para enviar

Defina um onclickouvinte no botão de validação para definir um sinalizador global (digamos justValidate) para indicar que esse clique tem como objetivo verificar a validação do formulário.

E defina um onclickouvinte no botão enviar para definir o justValidatesinalizador como falso.

Em seguida, no onsubmitmanipulador do formulário, você verifica o sinalizador justValidatepara decidir o valor de retorno e invoca o preventDefault()para interromper o envio do formulário. Como você sabe, a validação do formulário HTML5 (e a dica da GUI para o usuário) é realizada antes do onsubmitevento e, mesmo se o formulário for VÁLIDO, você pode interromper o envio do formulário retornando false ou invoke preventDefault().

E, no HTML5 você tem um método para verificar a validação do formulário: o form.checkValidity(), aí você pode saber se o formulário está validado ou não no seu código.

OK, aqui está a demonstração: http://jsbin.com/buvuku/2/edit

Xieranmaya
fonte
3

Não tenho certeza se vale a pena digitar tudo do zero, pois este artigo publicado em A List Apart faz um bom trabalho explicando isso. O MDN também tem um guia prático para formulários e validação de HTML5 (cobrindo a API e também o CSS relacionado).

Anatoli Papirovski
fonte
2

Um pouco mais fácil adicionar ou remover a validação HTML5 de conjuntos de campos.

 $('form').each(function(){

    // CLEAR OUT ALL THE HTML5 REQUIRED ATTRS
    $(this).find('.required').attr('required', false);

    // ADD THEM BACK TO THE CURRENT FIELDSET
    // I'M JUST USING A CLASS TO IDENTIFY REQUIRED FIELDS
    $(this).find('fieldset.current .required').attr('required', true);

    $(this).submit(function(){

        var current     = $(this).find('fieldset.current')
        var next        = $(current).next()

        // MOVE THE CURRENT MARKER
        $(current).removeClass('current');
        $(next).addClass('current');

        // ADD THE REQUIRED TAGS TO THE NEXT PART
        // NO NEED TO REMOVE THE OLD ONES
        // SINCE THEY SHOULD BE FILLED OUT CORRECTLY
        $(next).find('.required').attr('required', true);

    });

});
Wreleven
fonte
2

Parece que encontrei o truque: apenas remova o targetatributo do formulário e , em seguida, use um botão de envio para validar o formulário e mostrar dicas, verificar se o formulário é válido via JavaScript e, em seguida, postar o que for. O código a seguir funciona para mim:

<form>
  <input name="foo" required>
  <button id="submit">Submit</button>
</form>

<script>
$('#submit').click( function(e){
  var isValid = true;
  $('form input').map(function() {
    isValid &= this.validity['valid'] ;
  }) ;
  if (isValid) {
    console.log('valid!');
    // post something..
  } else
    console.log('not valid!');
});
</script>
Chenxin
fonte
Obrigado! É a verdadeira solução para jQuery.
Vuong
1

Código HTML:

<form class="validateDontSubmit">
....
<button style="dislay:none">submit</button>
</form>
<button class="outside"></button>

javascript (usando Jquery):

<script type="text/javascript">

$(document).on('submit','.validateDontSubmit',function (e) {
    //prevent the form from doing a submit
    e.preventDefault();
    return false;
})

$(document).ready(function(){
// using button outside trigger click
    $('.outside').click(function() {
        $('.validateDontSubmit button').trigger('click');
    });
});
</script>

Espero que isso te ajude

Hưng Trịnh
fonte
Por que está respondendo à pergunta?
executável de
usando HTML5 validar sem enviar. e usar dados de formulário para seu propósito: form_data = $ ('. validateDontSubmit'). serializeArray ();
Hưng Trịnh
1

var field = $("#field")
field.keyup(function(ev){
    if(field[0].value.length < 10) {
        field[0].setCustomValidity("characters less than 10")
        
    }else if (field[0].value.length === 10) {
        field[0].setCustomValidity("characters equal to 10")
        
    }else if (field[0].value.length > 10 && field[0].value.length < 20) {
        field[0].setCustomValidity("characters greater than 10 and less than 20")
        
    }else if(field[0].validity.typeMismatch) {
    	field[0].setCustomValidity("wrong email message")
        
    }else {
    	field[0].setCustomValidity("") // no more errors
        
    }
    field[0].reportValidity()
    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="email" id="field">

Ilya webdev
fonte
1
Você acrescentaria mais explicação?
zmag
-1

Quando há um processo de validação muito complexo (especialmente assíncrono), há uma solução alternativa simples:

<form id="form1">
<input type="button" onclick="javascript:submitIfVeryComplexValidationIsOk()" />
<input type="submit" id="form1_submit_hidden" style="display:none" />
</form>
...
<script>
function submitIfVeryComplexValidationIsOk() {
    var form1 = document.forms['form1']
    if (!form1.checkValidity()) {
        $("#form1_submit_hidden").click()
        return
    }

    if (checkForVeryComplexValidation() === 'Ok') {
         form1.submit()
    } else {
         alert('form is invalid')
    }
}
</script>
Nadi h
fonte
-2

Outra maneira de resolver esse problema:

$('input').oninvalid(function (event, errorMessage) {
    event.target.focus();
});
Vasyl Boiko
fonte
Não funciona para mim, eu recebo: Uncaught TypeError: $(...).oninvalid is not a functione não vejo isso nos documentos do jQuery.
MECU de
Eu acho que deveria estar dizendo "inválido" e não "oninvalid", pois você está usando jQuery aqui.
Enadon,