Se requiere un formulario HTML5. ¿Establecer mensaje de validación personalizado?

326

Tengo el siguiente formulario 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"/>

Actualmente cuando presiono enter cuando ambos están en blanco, aparece un cuadro emergente que dice "Por favor complete este campo". ¿Cómo cambiaría ese mensaje predeterminado a "Este campo no se puede dejar en blanco"?

EDITAR: también tenga en cuenta que el mensaje de error del campo de contraseña de tipo es simplemente *****. Para recrear esto, asigne un valor al nombre de usuario y presione enviar.

EDITAR : estoy usando Chrome 10 para las pruebas. Por favor haz lo mismo

Skizit
fuente
1
Oh, +1 para el loco mensaje de validación de contraseña vacía = / ¿Cómo pasó eso QA, me pregunto ...
David dice que reinstale a Mónica el
3
¿Por qué no simplemente aceptar el mensaje predeterminado del navegador? Eso es lo que los usuarios ven para cada otro sitio que visitan, solo confundirá a sus usuarios creando un mensaje no estándar. (¡Google probablemente ha logrado más evaluaciones y pruebas de UX para determinar esa redacción que usted!).
ChrisV
12
@ChrisV ¿Qué pasa con los sitios en varios idiomas?
inemanja
1
En mi caso, quiero verificar que el valor sea un número antes de publicarlo, pero no puedo usar el atributo type = "number" (por razones). Así que configuré el atributo del patrón para verificar los números y decimales opcionales que da el mensaje , "Haga coincidir el formato solicitado", en caso de error. Prefiero que diga: "Debes regalarnos un número".
Kristopher

Respuestas:

267

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

Me cambié a JavaScript básico de Mootools según lo sugerido por @itpastorn en los comentarios, pero usted debería ser capaz de trabajar en los Mootools equivalente si es necesario.

Editar

He actualizado el código aquí, ya que setCustomValidityfunciona de manera ligeramente diferente a lo que entendí cuando originalmente respondí. Si setCustomValidityse establece en otra cosa que no sea la cadena vacía, hará que el campo se considere no válido; por lo tanto, debe borrarlo antes de probar la validez, no puede simplemente configurarlo y olvidarlo.

Editar más

Como se señala en el comentario de @ thomasvdb a continuación, debe borrar la validez personalizada en algún evento fuera de lo invalidcontrario, de lo contrario, puede haber un pase adicional a través del oninvalidcontrolador para borrarlo.

robertc
fuente
Intenté esto pero todavía hay un error. Si deja el campo vacío, muestra el mensaje, luego ingrese algo en el campo, pero ahora muestra un mensaje vacío y la acción no se ejecuta. Si ahora vuelve a hacer clic en el botón, pasará.
thomasvdb
1
@thomasvdb Intente configurar la validez personalizada en una cadena vacía en el inputevento. Por el momento, solo se borra si invalidse dispara el evento.
robertc
Esta es de hecho la solución. Lo descubrí con la solución de @hleinone. ¡Gracias por la respuesta!
thomasvdb
44
La solución anterior solo usa JQuery para esperar a que se cargue el documento. Todo lo demás es puro JS y DOM. Un navegador lo suficientemente moderno como para admitir setCustomValidity también debería admitir el evento DOMContentLoaded, lo que significa que JQuery no es necesario, si no se usa para otra cosa.
itpastorn
1
@ Lai32290 porque no está accediendo al objeto DOM real. $("")devuelve una matriz de objetos, incluso si solo hay uno. $("")[i]es muy probable lo que quieres.
Noah Passalacqua
290

Aquí está el código para manejar el mensaje de error personalizado en HTML5

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

Esta parte es importante porque oculta el mensaje de error cuando el usuario ingresa nuevos datos:

oninput="this.setCustomValidity('')"
Somnath Kadam
fuente
Funciona perfectamente en Firefox 29.0 y Chrome 34.0.1847.137.
Fernando Kosh
perfecto y en FF 38 hasta ahora. Soluciona el error en la validación del correo electrónico si solo se usa oninvalid ().
Andrew
No funciona en Safari en el iPad ni en el iPhone. Sin embargo, funciona como se esperaba en el escritorio de Chrome.
Nabeel
2
@ somnath-kadam ¿Es un error o lo hizo intencionalmente oninput = "setCustomValidity ('')" en lugar de oninput = "this.setCustomValidity ('')"
tormuto
3
Gracias por marcar oninput = "setCustomValidity ('')" como lo más importante. Esto me salvó el día.
singhpradeep
99

Es muy simple controlar mensajes personalizados con la ayuda del HTML5eventooninvalid

Aquí está el código:

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

Esto es lo más importante:

onvalid="this.setCustomValidity('')"
Ashwini Jain
fuente
3
También verifique otras validaciones, como patrones, valores mínimos / máximos, etc. sanalksankar.blogspot.com/2010/12/…
Jaider
10
Esto causa un error en firefox donde se valida al actualizar, pero falla al cambiar y corregir.
Ryan Charmley
12
@RyanCharmley usando onchange="this.setCustomValidity('')"el error se habrá ido. Mira mi respuesta a continuación.
Salar
44
Si esto no funciona (no funciona en Safari, por ejemplo), use en oninputlugar de onvalid.
Jimothy
2
@Jimothy tiene razón sobre esto, oninputes la solución más universal, onvalidni siquiera funcionó en Chrome para mí.
ThisGuyCantEven
68

Nota: Esto ya no funciona en Chrome, no se ha probado en otros navegadores. Ver ediciones a continuación. Esta respuesta se deja aquí para referencia histórica.

Si considera que la cadena de validación realmente no debe establecerse por código, puede configurar el atributo de título del elemento de entrada para que lea "Este campo no puede dejarse en blanco". (Funciona en Chrome 10)

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

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

Y en Firefox, puede agregar este atributo:

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

Editar

Esto parece haber cambiado desde que originalmente escribí esta respuesta. Ahora agregar un título no cambia el mensaje de validez, solo agrega un anexo al mensaje. El violín de arriba todavía se aplica.

Editar 2

Chrome ahora no hace nada con el atributo de título a partir de Chrome 51. No estoy seguro de qué versión cambió.

kzh
fuente
1
Esto no cambia el contenido real del mensaje.
Wesley Murch
2
En el momento en que lo probé lo hice.
kzh
3
Mi error, OP especificó Chrome 10, estaba en FF5. Eliminado downvote, mis disculpas. Wow, ese mensaje de error en Chrome es lo más feo que he visto.
Wesley Murch
2
Para mensajes de error declarativos en Firefox use el atributo:x-moz-errormessage="This field should not be left blank."
robertc
2
Esto agrega un mensaje descriptivo debajo de "Por favor complete este campo".
Magne
41

Es muy sencillo controlar mensajes personalizados con la ayuda del HTML5 oninvalidevento.

Aquí está el código:

User ID 
<input id="UserID"  type="text" required 
       oninvalid="this.setCustomValidity('User ID is a must')">
Dharmendra Jha
fuente
44
es necesario establecer el mensaje de validez en blanco una vez que el control revela la entrada; de lo contrario, se mostrará el primer mensaje de validez ejecutado para todos los campos. Agregue oninput = "setCustomValidity ('')" siempre que llame a setCustomValidity (). +1 a la respuesta de Somnath.
Tarang
41

Al configurar y desarmar setCustomValidityen el momento adecuado, el mensaje de validación funcionará sin problemas.

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

Usé en onchangelugar de lo oninputque es más general y ocurre cuando el valor se cambia en cualquier condición, incluso a través de JavaScript.

Salar
fuente
Esta debería ser la respuesta aceptada. Trabajó en Windows 10 1709 en los siguientes 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. Trabajó en macOS 10.13.2 en Safari 11.0 (13604.1.38.1.6). Funcionó en Android 4.4.4 en Chrome 66.0.3359.158. Para aquellos que buscan la forma JSX: onInvalid={(e) => { e.target.setCustomValidity('foo') }} onChange={(e) => { e.target.setCustomValidity('') }}.
GuiRitter
Anexo: epuede ser nulo, por ejemplo, cuando se elimina una opción de un campo React Select. No te olvides de verificar eso.
GuiRitter
Errata: para usar esto con React Select, tienes que pasar onChangey onInvalidcomoinputProps={{ onInvalid: …, onChange: …, }}
GuiRitter
Adición: type='email'es un poco más difícil de tratar, ya que el uso de setCustomValidityconjuntos customError: truede e.target.validityincluso si la entrada es válida. Estoy tratando de encontrar una manera de arreglarlo.
GuiRitter
@GuiRitter ¿Te diste cuenta de esto?
EvilJordan
39

He creado una pequeña biblioteca para facilitar el cambio y la traducción de los mensajes de error. Incluso puede cambiar los textos por tipo de error que actualmente no está disponible titleen Chrome o x-moz-errormessageFirefox. Ve a verlo en GitHub y da tu opinión.

Se usa como:

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

Hay una demostración disponible en jsFiddle .

hleinona
fuente
¡Gracias! Resuelto mi pequeño error mencionado como comentario en la respuesta aceptada.
thomasvdb
Buena respuesta, ya que OP está utilizando Google Chrome; piensa que esto no funcionará en IE Edge
CoderHawk
23

Prueba este, es mejor y probado:

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

Manifestación:

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

Rikin Patel
fuente
hey ... buena solución pero type = email no funciona en el navegador safari. echar un vistazo w3schools.com/html/html_form_input_types.asp
Bhawna Malhotra
2
Sí, no es compatible con safari, pero di una respuesta para establecer un mensaje de validación personalizado.
Rikin Patel
10

La forma más fácil y limpia que he encontrado es utilizar un atributo de datos para almacenar su error personalizado. Pruebe la validez del nodo y maneje el error utilizando algunos html personalizados.ingrese la descripción de la imagen aquí

le javascript

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

y algunos súper HTML5

<input type="text" id="city" name="city" data-pattern-error="Please use only letters for your city." pattern="[A-z ']*" required>
Collin White
fuente
3
A pesar del error que dice solo letras, ¿el patrón permite espacio y apóstrofe? Además, A-zpermite '[', '\', ']', '^', '_' y '' '.
Lawrence Dol
5

La solución para evitar mensajes de error de Google Chrome al ingresar 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
fuente
3

Tengo una solución más simple de vanilla js:

Para casillas de verificación:

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
fuente
1

Adaptando la respuesta de Salar a JSX y React, noté que React Select no se comporta como un <input/>campo con respecto a la validación. Aparentemente, se necesitan varias soluciones para mostrar solo el mensaje personalizado y evitar que se muestre en momentos inconvenientes.

He planteado un problema aquí , si ayuda algo. Aquí hay un CodeSandbox con un ejemplo de trabajo, y el código más importante allí se reproduce aquí:

Hola.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
fuente
1

De acuerdo, oninvalid funciona bien pero muestra un error incluso si el usuario ingresó datos válidos. Así que he utilizado a continuación para abordarlo, espero que también funcione para ti,

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

Umesh Patil
fuente
-7

Se puede manejar fácilmente simplemente poniendo 'título' con el campo:

<input type="text" id="username" required title="This field can not be empty"  />
Deepti
fuente
Esto no cambia el mensaje de error que se muestra. Solo muestra un título en la entrada cuando pasa el mouse por encima.
Mathieu Dumoulin
Esta no es la usabilidad correcta de "título" para mostrar alguna alerta para el campo de entrada.
Sajad Saderi