JSFiddle - React, Tailwind, and code Playground
HTML
<form name="form" id="form">
<label for="nome">Nome <small>(obrigatório)</small></label>
<input type="text" name="nome" data-required="true" />
<small class="erro">Nome obrigatório</small>
<label for="end">Endereço <small>(Não obrigatório)</small></label>
<input type="text" name="end"/>
<label for="end">Mensagem <small>(Obrigatório)</small></label>
<textarea name="msg" data-required="true"></textarea>
<small class="erro">Mensagem obrigatória</small>
<button type="submit">Enviar</button>
</form>
CSS
label,input,textarea,button{display: block;}
small.erro {display:none; color:red;}
JavaScript
$.validate = {
classErro: '.erro', //classe padrão de exibição de erros
start: function(form){ // função para inicializar
//testa todos os campos que tiverem o atributo data-required
$(form+' *[data-required]').on('blur',function(){
if ($(this).val() == ''){
$(this).next($.validate.classErro).show();
} else {
$(this).next($.validate.classErro).hide();
}
});
$(document).ready(function(){
//testa o form no momento do submit
$(form).submit(function(event){
if(!$.validate.validSubmit(form)){
//se não passar na validação impede o submit
event.preventDefault();
}
});
});
},
//função para validar no momento do submit
validSubmit: function(form){
// procura por campos com attr required
$(form+' *[data-required]').each(function(){
if ($(this).val() == ''){
$(this).next($.validate.classErro).show();
} else {
$(this).next($.validate.classErro).hide();
}
});
// se houver erro retorna falso
if($(form+' small.erro:visible').length > 0){
return false;
}
return true;
}
};
// inicia a função passando como parametro o id do form
$.validate.start('#form');