Attribut requis du formulaire HTML5. Définir un message de validation personnalisé?

326

J'ai le formulaire HTML5 suivant: 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"/>

Actuellement, lorsque je clique sur Entrée alors qu'ils sont tous deux vides, une boîte de dialogue apparaît indiquant "Veuillez remplir ce champ". Comment changer ce message par défaut en "Ce champ ne peut pas être laissé vide"?

EDIT: Notez également que le message d'erreur du champ de mot de passe de type est simplement *****. Pour recréer cela, donnez une valeur au nom d'utilisateur et cliquez sur soumettre.

EDIT : J'utilise Chrome 10 pour les tests. Veuillez faire de même

Skizit
la source
1
Oh, +1 pour le message de validation de mot de passe vide insensé = / Comment cela a-t-il réussi l'AQ, je me demande ...
David dit réintégrer Monica le
3
Pourquoi ne pas simplement accepter le message par défaut du navigateur? C'est ce que les utilisateurs voient pour tous les autres sites qu'ils visitent, vous confondrez simplement vos utilisateurs en créant un message non standard. (Google a probablement réussi plus d'évaluations et de tests UX pour déterminer ce libellé que vous n'en avez!).
ChrisV
12
@ChrisV Qu'en est-il des sites multilingues?
inemanja
1
Dans mon cas, je veux vérifier que la valeur est un nombre avant de poster, mais je ne peux pas utiliser l'attribut type = "number" (pour des raisons.) J'ai donc défini l'attribut pattern pour vérifier les nombres et les décimales facultatives qui donnent le message , "Veuillez faire correspondre le format demandé", en cas d'erreur. Je préfère qu'il soit dit: "Vous devez nous offrir un bucko numérique."
Kristopher

Réponses:

267

Utilisation 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("");
        };
    }
})

J'ai changé pour vanilla JavaScript de Mootools comme suggéré par @itpastorn dans les commentaires, mais vous devriez être en mesure de trouver l'équivalent de Mootools si nécessaire.

Éditer

J'ai mis à jour le code ici car il setCustomValidityfonctionne légèrement différemment de ce que j'ai compris lorsque j'ai répondu à l'origine. Si setCustomValidityest défini sur autre chose que la chaîne vide, le champ sera considéré comme non valide; par conséquent, vous devez l'effacer avant de tester la validité, vous ne pouvez pas simplement le définir et l'oublier.

Modifier davantage

Comme indiqué dans le commentaire de @ thomasvdb ci-dessous, vous devez effacer la validité personnalisée dans certains cas en dehors invalidsinon il peut y avoir un passage supplémentaire via le oninvalidgestionnaire pour l'effacer.

robertc
la source
J'ai essayé mais il y a toujours une erreur. Si vous laissez le champ vide, il affiche le message, puis entrez quelque chose dans le champ, mais il affiche maintenant un message vide et l'action n'est pas exécutée. Si vous cliquez à nouveau sur le bouton, il passera.
thomasvdb
1
@thomasvdb Essayez de définir la validité personnalisée sur une chaîne vide sur l' inputévénement. Pour le moment, cela n'est effacé que si l' invalidévénement est déclenché.
robertc
Telle est bien la solution. Je l'ai découvert avec la solution de @hleinone. Merci pour la réponse!
thomasvdb
4
La solution ci-dessus utilise uniquement JQuery pour attendre le chargement du document. Tout le reste est pur JS et DOM. Un navigateur suffisamment moderne pour prendre en charge setCustomValidity devrait également prendre en charge l'événement DOMContentLoaded, ce qui signifie que JQuery n'est pas nécessaire s'il n'est utilisé pour rien d'autre.
itpastorn
1
@ Lai32290 car vous n'accédez pas à l'objet DOM réel. $("")renvoie un tableau d'objets, même s'il n'y en a qu'un. $("")[i]est très probablement ce que vous voulez.
Noah Passalacqua
290

Voici le code pour gérer les messages d'erreur personnalisés en HTML5

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

Cette partie est importante car elle masque le message d'erreur lorsque l'utilisateur entre de nouvelles données:

oninput="this.setCustomValidity('')"
Somnath Kadam
la source
Fonctionne parfaitement sur Firefox 29.0 et Chrome 34.0.1847.137.
Fernando Kosh
parfait et en FF 38 jusqu'à présent. Correction d'un bug dans la validation des e-mails si seulement oninvalid () est utilisé.
andrew
Ne fonctionne pas dans Safari sur iPad ou iPhone. Fonctionne comme prévu sur le bureau Chrome.
Nabeel
2
@ somnath-kadam Est-ce une erreur ou vous avez intentionnellement fait oninput = "setCustomValidity ('')" au lieu de oninput = "this.setCustomValidity ('')"
tormuto
3
Merci d'avoir marqué oninput = "setCustomValidity ('')" comme le plus important. Cela m'a sauvé la journée.
singhpradeep
99

Il est très simple de contrôler les messages personnalisés à l'aide de l' HTML5événementoninvalid

Voici le code:

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

C'est le plus important:

onvalid="this.setCustomValidity('')"
Ashwini Jain
la source
3
Vérifiez également d'autres validations telles que le modèle, les valeurs min / max, etc ... sanalksankar.blogspot.com/2010/12/…
Jaider
10
Cela provoque un bogue dans Firefox où il est validé lors de l'actualisation, mais échoue lors du changement et de la correction.
Ryan Charmley
12
@RyanCharmley en utilisant onchange="this.setCustomValidity('')"le bogue aura disparu. Vérifiez ma réponse ci-dessous.
Salar du
4
Si cela ne fonctionne pas (ce n'est pas le cas dans Safari, par exemple), utilisez oninputau lieu de onvalid.
Jimothy
2
@Jimothy a raison à ce sujet, oninputest la solution la plus universelle, onvalidne fonctionnait même pas dans Chrome pour moi.
ThisGuyCantEven
68

Remarque: cela ne fonctionne plus dans Chrome, non testé dans d'autres navigateurs. Voir les modifications ci-dessous. Cette réponse est laissée ici pour référence historique.

Si vous pensez que la chaîne de validation ne doit vraiment pas être définie par du code, vous pouvez définir l'attribut title de l'élément d'entrée pour lire "Ce champ ne peut pas être laissé vide". (Fonctionne dans Chrome 10)

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

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

Et dans Firefox, vous pouvez ajouter cet attribut:

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

Éditer

Cela semble avoir changé depuis que j'ai écrit cette réponse à l'origine. Maintenant, l'ajout d'un titre ne modifie pas le message de validité, il ajoute simplement un addendum au message. Le violon ci-dessus s'applique toujours.

Modifier 2

Chrome ne fait plus rien avec l'attribut title à partir de Chrome 51. Je ne sais pas dans quelle version cela a changé.

kzh
la source
1
Cela ne change pas le contenu réel du message.
Wesley Murch
2
Au moment où je l'ai testé, c'était le cas.
kzh
3
Mon erreur, OP a spécifié Chrome 10, j'étais sur FF5. Suppression du downvote, mes excuses. Wow, ce message d'erreur dans Chrome est la chose la plus laide que j'aie jamais vue.
Wesley Murch
2
Pour les messages d'erreur déclaratifs dans Firefox, utilisez l'attribut:x-moz-errormessage="This field should not be left blank."
robertc
2
Cela ajoute un message descriptif sous le "Veuillez remplir ce champ".
Magne
41

Il est très simple de contrôler les messages personnalisés à l'aide de l' HTML5 oninvalidévénement

Voici le code:

User ID 
<input id="UserID"  type="text" required 
       oninvalid="this.setCustomValidity('User ID is a must')">
Dharmendra Jha
la source
4
il est nécessaire de mettre le message de validité à blanc une fois que le contrôle a reçu l'entrée sinon le premier message de validité exécuté sera affiché pour tous les champs. Ajoutez oninput = "setCustomValidity ('')" chaque fois que vous appelez setCustomValidity (). +1 à la réponse de Somnath.
Tarang
41

En définissant et en désélectionnant le setCustomValidityau bon moment, le message de validation fonctionnera parfaitement.

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

J'ai utilisé onchangeau lieu de oninputce qui est plus général et se produit lorsque la valeur est modifiée dans n'importe quelle condition, même via JavaScript.

Salar
la source
Ce devrait être la réponse acceptée. Fonctionné sous Windows 10 1709 dans les navigateurs suivants: Chrome 66.0.3359.139 64 bits, Firefox 59.0.3 (64 bits), Internet Explorer 11.431.16299.0, Edge 41.16299.402.0. Fonctionné sous macOS 10.13.2 dans Safari 11.0 (13604.1.38.1.6). Fonctionné dans Android 4.4.4 dans Chrome 66.0.3359.158. Pour ceux qui recherchent la manière JSX: onInvalid={(e) => { e.target.setCustomValidity('foo') }} onChange={(e) => { e.target.setCustomValidity('') }}.
GuiRitter
Addendum: epeut être nul, par exemple lorsqu'une option est supprimée d'un champ React Select. N'oubliez pas de vérifier cela.
GuiRitter
Errata: pour l'utiliser avec React Select, vous devez passer onChangeet onInvalidasinputProps={{ onInvalid: …, onChange: …, }}
GuiRitter
Addendum: type='email'est un peu plus difficile à traiter, car l'utilisation de setCustomValiditysets customError: trueà e.target.validitymême si l'entrée est valide. J'essaie de trouver un moyen de le réparer.
GuiRitter
@GuiRitter Avez-vous compris cela?
EvilJordan
39

J'ai créé une petite bibliothèque pour faciliter la modification et la traduction des messages d'erreur. Vous pouvez même modifier les textes par type d'erreur qui n'est actuellement pas disponible à l'aide titlede Chrome ou x-moz-errormessagede Firefox. Allez le vérifier sur GitHub et donnez votre avis.

Il est utilisé comme:

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

Il y a une démo disponible sur jsFiddle .

hleinone
la source
Merci! Résolu mon petit bug mentionné comme commentaire dans la réponse acceptée.
thomasvdb
Bonne réponse, car OP utilise Google Chrome; bien que cela ne fonctionne pas dans IE Edge
CoderHawk
23

Essayez celui-ci, son meilleur et testé:

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;
}

Démo:

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

Rikin Patel
la source
hey .... belle solution mais type = email ne fonctionne pas dans le navigateur safari. jetez un oeil w3schools.com/html/html_form_input_types.asp
Bhawna Malhotra
2
Oui, il n'est pas pris en charge pour safari, mais j'ai donné une réponse pour définir un message de validation personnalisé.
Rikin Patel
10

Le moyen le plus simple et le plus propre que j'ai trouvé consiste à utiliser un attribut de données pour stocker votre erreur personnalisée. Testez la validité du nœud et gérez l'erreur en utilisant du code HTML personnalisé.entrez la description de l'image ici

le javascript

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

et du 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
la source
3
Malgré l'erreur ne disant que des lettres, le motif autorise l'espace et l'apostrophe? Autorise également A-z'[', '\', ']', '^', '_' et '' '.
Lawrence Dol
5

La solution pour éviter les messages d'erreur Google Chrome lors de la saisie de chaque symbole:

<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
la source
3

J'ai une seule solution simple vanille js:

Pour les cases à cocher:

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

Pour les entrées:

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

En adaptant la réponse de Salar à JSX et React, j'ai remarqué que React Select ne se comportait pas comme un <input/>champ concernant la validation. Apparemment, plusieurs solutions de contournement sont nécessaires pour afficher uniquement le message personnalisé et l'empêcher de s'afficher à des moments incommodes.

J'ai soulevé un problème ici , si cela peut aider quelque chose. Voici un CodeSandbox avec un exemple de travail, et le code le plus important y est reproduit ici:

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
la source
1

D'accord, oninvalid fonctionne bien mais il affiche une erreur même si l'utilisateur a entré des données valides. J'ai donc utilisé ci-dessous pour y faire face, j'espère que cela fonctionnera aussi pour vous,

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

Umesh Patil
la source
-7

Peut être facilement géré en mettant simplement 'title' dans le champ:

<input type="text" id="username" required title="This field can not be empty"  />
Deepti
la source
Cela ne change pas le message d'erreur affiché. Il affiche uniquement un titre sur l'entrée lorsque vous survolez.
Mathieu Dumoulin
Ce n'est pas l'utilisabilité correcte de "title" pour afficher une alerte pour le champ de saisie.
sajad saderi