Atributo obrigatório do formulário HTML5. Definir mensagem de validação personalizada?

326

Eu tenho o seguinte formulário HTML5: http://jsfiddle.net/nfgfP/

<form id="form" onsubmit="return(login())">
<input name="username" placeholder="Username" required />
<input name="pass"  type="password" placeholder="Password" required/>
<br/>Remember me: <input type="checkbox" name="remember" value="true" /><br/>
<input type="submit" name="submit" value="Log In"/>

Atualmente, quando clico em enter quando ambos estão em branco, uma caixa pop-up é exibida com a mensagem "Por favor, preencha este campo". Como eu alteraria essa mensagem padrão para "Este campo não pode ser deixado em branco"?

EDIT: Observe também que a mensagem de erro do campo de senha do tipo é simples *****. Para recriar isso, atribua um valor ao nome de usuário e clique em enviar.

EDIT : estou usando o Chrome 10 para testes. Faça o mesmo

Skizit
fonte
1
Oh, uma para a mensagem de validação vazia por senha insano = / Como é que isso passe QA, eu me pergunto ...
David diz Reintegrar Monica
3
Por que não apenas aceitar a mensagem padrão do navegador? É isso que os usuários veem em todos os outros sites que visitam; você apenas confunde seus usuários criando uma mensagem não padrão. (O Google provavelmente gerenciou mais avaliações e testes de experiência do usuário para determinar essas palavras do que você!).
ChrisV
12
@ChrisV E os sites multilíngues?
Inemanja
1
No meu caso, quero verificar se o valor é um número antes de postar, mas não posso usar o atributo type = "number" (por razões.) Portanto, defino o atributo pattern para verificar se há números e decimais opcionais que dão a mensagem , "Corresponde ao formato solicitado", por erro. Prefiro que ele diga: "Você deve nos presentear com um número".
29517 Kristopher

Respostas:

267

Use setCustomValidity:

document.addEventListener("DOMContentLoaded", function() {
    var elements = document.getElementsByTagName("INPUT");
    for (var i = 0; i < elements.length; i++) {
        elements[i].oninvalid = function(e) {
            e.target.setCustomValidity("");
            if (!e.target.validity.valid) {
                e.target.setCustomValidity("This field cannot be left blank");
            }
        };
        elements[i].oninput = function(e) {
            e.target.setCustomValidity("");
        };
    }
})

I alteradas para baunilha JavaScript de Mootools como sugerido por @itpastorn nos comentários, mas você deve ser capaz de trabalhar as Mootools equivalente, se necessário.

Editar

Atualizei o código aqui, pois setCustomValidityfunciona um pouco diferente do que eu entendi quando respondi originalmente. Se setCustomValidityfor definido como algo diferente da sequência vazia, fará com que o campo seja considerado inválido; portanto, você deve limpá-lo antes de testar a validade, não pode simplesmente configurá-lo e esquecer.

Edição adicional

Conforme indicado no comentário do @ thomasvdb abaixo, você precisa limpar a validade personalizada em algum evento fora de invalidoutro caso, pode haver uma passagem extra pelo oninvalidmanipulador para limpá-la.

robertc
fonte
Eu tentei isso, mas ainda há um erro. Se você deixar o campo vazio, ele mostrará a mensagem e, em seguida, insira algo no campo, mas agora mostrará uma mensagem vazia e a ação não será executada. Se você agora clicar no botão novamente, ele será exibido.
Thomasvdb 6/09/12
1
@thomasvdb Tente configurar a validade personalizada para uma sequência vazia no inputevento. No momento, só será liberado se o invalidevento for disparado.
robertc 6/09/12
Esta é realmente a solução. Descobri com a solução do @hleinone. Obrigado pela resposta!
thomasvdb
4
A solução acima usa apenas o JQuery para aguardar o carregamento do documento. Tudo o resto é puro JS e DOM. Um navegador moderno o suficiente para suportar o setCustomValidity também deve suportar o evento DOMContentLoaded, o que significa que o JQuery não é necessário, se não for usado para mais nada.
precisa saber é o seguinte
1
@ Lai32290 porque você não está acessando o objeto DOM real. $("")retorna uma matriz de objetos, mesmo se houver apenas um. $("")[i]provavelmente é o que você deseja.
Noah Passalacqua
290

Aqui está o código para lidar com mensagens de erro personalizadas em HTML5

<input type="text" id="username" required placeholder="Enter Name"
    oninvalid="this.setCustomValidity('Enter User Name Here')"
    oninput="this.setCustomValidity('')"  />

Esta parte é importante porque oculta a mensagem de erro quando o usuário insere novos dados:

oninput="this.setCustomValidity('')"
Somnath Kadam
fonte
Funciona perfeitamente no Firefox 29.0 e no Chrome 34.0.1847.137.
Fernando Kosh
perfeito e em FF 38 até agora. Corrige o erro na validação de email se apenas oninvalid () for usado.
andrew
Não funciona no Safari no iPad nem no iPhone. Porém, funcionando como esperado na área de trabalho do Chrome.
Nabeel
2
@ somnath-kadam É um erro ou você intencionalmente fez oninput = "setCustomValidity ('')" em vez de oninput = "this.setCustomValidity ('')"
tormuto
3
Obrigado por marcar oninput = "setCustomValidity ('')" como o mais importante. Isso salvou meu dia.
singhpradeep
99

É muito simples controlar mensagens personalizadas com a ajuda do HTML5eventooninvalid

Aqui está o código:

<input id="UserID"  type="text" required="required"
       oninvalid="this.setCustomValidity('Witinnovation')"
       onvalid="this.setCustomValidity('')">

Isso é mais importante:

onvalid="this.setCustomValidity('')"
Ashwini Jain
fonte
3
Vá também outros validações, bem como o padrão, min / max valores, etc ... sanalksankar.blogspot.com/2010/12/...
Jaider
10
Isso causa um erro no firefox, que é validado na atualização, mas falha na alteração e correção.
Ryan Charmley
12
@RyanCharmley usando onchange="this.setCustomValidity('')"o bug desaparecerá. Verifique minha resposta abaixo.
Salar
4
Se isso não funcionar (no Safari, por exemplo), use em oninputvez de onvalid.
Jimothy
2
@Jimothy está certo sobre isso, oninputé a solução mais universal, onvalidnão funcionou nem no Chrome para mim.
ThisGuyCantEven
68

Nota: isso não funciona mais no Chrome, não é testado em outros navegadores. Veja as edições abaixo. Esta resposta está sendo deixada aqui para referência histórica.

Se você achar que a sequência de validação realmente não deve ser definida por código, defina o atributo title do elemento de entrada como "Este campo não pode ser deixado em branco". (Funciona no Chrome 10)

title="This field should not be left blank."

Veja http://jsfiddle.net/kaleb/nfgfP/8/

E no Firefox, você pode adicionar este atributo:

x-moz-errormessage="This field should not be left blank."

Editar

Isso parece ter mudado desde que escrevi originalmente esta resposta. Agora, adicionar um título não altera a mensagem de validade, apenas adiciona um adendo à mensagem. O violino acima ainda se aplica.

Editar 2

Agora, o Chrome não faz nada com o atributo title do Chrome 51. Não sei em que versão isso foi alterado.

kzh
fonte
1
Isso não altera o conteúdo real da mensagem.
Wesley Murch #
2
No momento em que eu testei, fiz.
kzh
3
Meu erro, o OP especificou o Chrome 10, eu estava no FF5. Removido voto negativo, minhas desculpas. Uau, essa mensagem de erro no Chrome é a coisa mais feia que eu já vi.
Wesley Murch #
2
Para mensagens de erro declarativas no Firefox, use o atributo:x-moz-errormessage="This field should not be left blank."
robertc
2
Isso adiciona uma mensagem descritiva no campo "Por favor, preencha este campo".
Magne
41

É muito simples controlar mensagens personalizadas com a ajuda do HTML5 oninvalidevento

Aqui está o código:

User ID 
<input id="UserID"  type="text" required 
       oninvalid="this.setCustomValidity('User ID is a must')">
Dharmendra Jha
fonte
4
é necessário configurar a mensagem de validade como em branco quando o controle receber entrada, caso contrário, a primeira mensagem de validade executada será exibida para todos os campos. Adicione oninput = "setCustomValidity ('')" sempre que chamar setCustomValidity (). +1 na resposta de Somnath.
quer
41

Ao definir e desmarcar a setCustomValidityhora certa, a mensagem de validação funcionará perfeitamente.

<input name="Username" required 
oninvalid="this.setCustomValidity('Username cannot be empty.')" 
onchange="this.setCustomValidity('')" type="text" />

Eu usei em onchangevez de oninputqual é mais geral e ocorre quando o valor é alterado em qualquer condição, mesmo através do JavaScript.

Salar
fonte
Essa deve ser a resposta aceita. Trabalhou no Windows 10 1709 nos seguintes navegadores: Chrome 66.0.3359.139 64 bits, Firefox 59.0.3 (64 bits), Internet Explorer 11.431.16299.0, Edge 41.16299.402.0. Trabalhou no macOS 10.13.2 no Safari 11.0 (13604.1.38.1.6). Trabalhou no Android 4.4.4 no Chrome 66.0.3359.158. Para aqueles que procuram o caminho JSX: onInvalid={(e) => { e.target.setCustomValidity('foo') }} onChange={(e) => { e.target.setCustomValidity('') }}.
GuiRitter
Adendo: epode ser nulo, por exemplo, quando uma opção é removida de um campo React Select. Não se esqueça de verificar isso.
GuiRitter #
Errata: para usar esta com Reagir Select, você tem que passar onChangee onInvalidcomoinputProps={{ onInvalid: …, onChange: …, }}
GuiRitter
Adendo: type='email'é um pouco mais difícil de tratar, pois o uso de setCustomValidityconjuntoscustomError: true de e.target.validitymesmo que a entrada é válida. Estou tentando encontrar uma maneira de consertar isso.
GuiRitter
@GuiRitter Você descobriu isso?
EvilJordan
39

Criei uma pequena biblioteca para facilitar a alteração e tradução das mensagens de erro. Você pode até alterar os textos por tipo de erro, que não está disponível titleno momento no Chrome ou x-moz-errormessageno Firefox. Vá conferir no GitHub e dê feedback.

É usado como:

<input type="email" required data-errormessage-value-missing="Please input something">

Há uma demonstração disponível no jsFiddle .

hleinone
fonte
Obrigado! Resolvi meu pequeno bug mencionado como um comentário na resposta aceita.
Thomasvdb 6/09/12
Boa resposta, já que o OP está usando o Google Chrome; thoug isto não vai funcionar no IE Borda
CoderHawk
23

Experimente este, é melhor e testado:

HTML:

<form id="myform">
    <input id="email" 
           oninvalid="InvalidMsg(this);" 
           oninput="InvalidMsg(this);"
           name="email"  
           type="email" 
           required="required" />
    <input type="submit" />
</form>

JAVASCRIPT:

function InvalidMsg(textbox) {
    if (textbox.value === '') {
        textbox.setCustomValidity('Required email address');
    } else if (textbox.validity.typeMismatch){
        textbox.setCustomValidity('please enter a valid email address');
    } else {
       textbox.setCustomValidity('');
    }

    return true;
}

Demo:

http://jsfiddle.net/patelriki13/Sqq8e/

Rikin Patel
fonte
ei .... boa solução, mas type = email não funciona no navegador safari. ter um olhar w3schools.com/html/html_form_input_types.asp
Bhawna Malhotra
2
Sim, não há suporte para o safari, mas dei uma resposta para definir a mensagem de validação personalizada.
Rikin Patel
10

A maneira mais fácil e limpa que encontrei é usar um atributo de dados para armazenar seu erro personalizado. Teste a validade do nó e lide com o erro usando algum html personalizado.insira a descrição da imagem aqui

le javascript

if(node.validity.patternMismatch)
        {
            message = node.dataset.patternError;
        }

e alguns super HTML5

<input type="text" id="city" name="city" data-pattern-error="Please use only letters for your city." pattern="[A-z ']*" required>
Collin White
fonte
3
Apesar do erro de dizer apenas letras, o padrão permite espaço e apóstrofo? Além disso, A-zpermite '[', '\', ']', '^', '_' e '' '.
Lawrence Dol
5

A solução para evitar mensagens de erro do Google Chrome ao inserir cada símbolo:

<p>Click the 'Submit' button with empty input field and you will see the custom error message. Then put "-" sign in the same input field.</p>
<form method="post" action="#">
  <label for="text_number_1">Here you will see browser's error validation message on input:</label><br>
  <input id="test_number_1" type="number" min="0" required="true"
         oninput="this.setCustomValidity('')"
         oninvalid="this.setCustomValidity('This is my custom message.')"/>
  <input type="submit"/>
</form>

<form method="post" action="#">
  <p></p>
  <label for="text_number_1">Here you will see no error messages on input:</label><br>
  <input id="test_number_2" type="number" min="0" required="true"
         oninput="(function(e){e.setCustomValidity(''); return !e.validity.valid && e.setCustomValidity(' ')})(this)"
         oninvalid="this.setCustomValidity('This is my custom message.')"/>
  <input type="submit"/>
</form>

Andrei Veshtard
fonte
3

Eu tenho uma solução mais simples vanilla js only:

Para caixas de seleção:

document.getElementById("id").oninvalid = function () {
    this.setCustomValidity(this.checked ? '' : 'My message');
};

Para entradas:

document.getElementById("id").oninvalid = function () {
    this.setCustomValidity(this.value ? '' : 'My message');
};
Bernhardh
fonte
1

Adaptando a resposta de Salar para JSX e React, notei que o React Select não se comporta exatamente como um <input/>campo em relação à validação. Aparentemente, são necessárias várias soluções alternativas para mostrar apenas a mensagem personalizada e impedir que ela seja exibida em momentos inconvenientes.

Eu levantei um problema aqui , se isso ajudar alguma coisa. Aqui está um CodeSandbox com um exemplo de trabalho, e o código mais importante lá é reproduzido aqui:

Hello.js

import React, { Component } from "react";
import SelectValid from "./SelectValid";

export default class Hello extends Component {
  render() {
    return (
      <form>
        <SelectValid placeholder="this one is optional" />
        <SelectValid placeholder="this one is required" required />
        <input
          required
          defaultValue="foo"
          onChange={e => e.target.setCustomValidity("")}
          onInvalid={e => e.target.setCustomValidity("foo")}
        />
        <button>button</button>
      </form>
    );
  }
}

SelectValid.js

import React, { Component } from "react";
import Select from "react-select";
import "react-select/dist/react-select.css";

export default class SelectValid extends Component {
  render() {
    this.required = !this.props.required
      ? false
      : this.state && this.state.value ? false : true;
    let inputProps = undefined;
    let onInputChange = undefined;
    if (this.props.required) {
      inputProps = {
        onInvalid: e => e.target.setCustomValidity(this.required ? "foo" : "")
      };
      onInputChange = value => {
        this.selectComponent.input.input.setCustomValidity(
          value
            ? ""
            : this.required
              ? "foo"
              : this.selectComponent.props.value ? "" : "foo"
        );
        return value;
      };
    }
    return (
      <Select
        onChange={value => {
          this.required = !this.props.required ? false : value ? false : true;
          let state = this && this.state ? this.state : { value: null };
          state.value = value;
          this.setState(state);
          if (this.props.onChange) {
            this.props.onChange();
          }
        }}
        value={this && this.state ? this.state.value : null}
        options={[{ label: "yes", value: 1 }, { label: "no", value: 0 }]}
        placeholder={this.props.placeholder}
        required={this.required}
        clearable
        searchable
        inputProps={inputProps}
        ref={input => (this.selectComponent = input)}
        onInputChange={onInputChange}
      />
    );
  }
}
GuiRitter
fonte
1

Ok, oninvalid funciona bem, mas mostra erro, mesmo que o usuário tenha inserido dados válidos. Então, eu usei abaixo para resolver isso, espero que funcione para você também,

oninvalid="this.setCustomValidity('Your custom message.')" onkeyup="setCustomValidity('')"

Umesh Patil
fonte
-7

Pode ser facilmente manipulado, basta colocar 'title' no campo:

<input type="text" id="username" required title="This field can not be empty"  />
Deepti
fonte
Isso não altera a mensagem de erro exibida. Ele mostra apenas um título na entrada quando você passa o mouse.
Mathieu Dumoulin
Esta não é a usabilidade correta de "title" para mostrar algum alerta para o campo de entrada.
sajad saderi 11/04