Quais São Algumas Formas de Validar Formulários Usando JavaScript?

In a previous lesson, you've learned how to use HTML to restrict the values your users can submit in your form. Mas às vezes isso não é suficiente. Se você quiser algo mais complexo, como exibir suas próprias mensagens de erro para o usuário, será necessário usar JavaScript. Certos elementos HTML, como os elementos textarea e input, expõem uma Constraint Validation API. Esta API permite que você afirme que o valor fornecido pelo usuário para esse elemento passa por qualquer validação em nível HTML que você tenha escrito, como comprimento mínimo ou correspondência de padrão. Mas como você pode realmente usá-lo? Vamos supor que você queira que os funcionários de uma empresa enviem mensagens de feedback através de um formulário como este:
<link rel="stylesheet" href="styles.css" />
<form>
  <label>Enter your email: </label>
  <input required type="email" />

  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>

  <button type="submit">Submit Feedback</button>
</form>
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}
Estamos usando o input de email que vem com validação embutida para verificar validações básicas como se o input inclui o sinal de arroba (@). Mas e se o usuário fornecer um endereço de email como example@email.com? Isso passaria na validação básica, mas queremos ser mais específicos sobre aceitar emails daqueles que possuem um endereço de email corporativo. Aqui é onde podemos usar o atributo pattern para especificar que o endereço de email deve terminar em um endereço de email da empresa. Aqui está como o exemplo atualizado ficará:
<link rel="stylesheet" href="styles.css" />
<form>
  <label>Enter your email: </label>
  <input required placeholder="username@sampleCompany.com" type="email" pattern=".+@sampleCompany\.com" />

  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>

  <button type="submit">Submit Feedback</button>
</form>
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}
Agora, se você tentar enviar o feedback, verá uma mensagem dizendo "Please match the requested format." Embora o input tenha texto de espaço reservado mostrando a eles o formato desejado, seria melhor também incluir uma mensagem de erro personalizada usando JavaScript. Vamos primeiro dar uma olhada no método checkValidity():
<link rel="stylesheet" href="styles.css" />
<form>
  <label>Enter your email: </label>
  <input required placeholder="username@sampleCompany.com" type="email" pattern=".+@sampleCompany\.com" />

  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>

  <button type="submit">Submit Feedback</button>
</form>
<script src="index.js"></script>
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}
const input = document.querySelector("input");

input.addEventListener("input", (e) => {
  console.log(e.target.checkValidity())
})
No exemplo acima, consultamos nossa entrada no DOM e adicionamos um listener de evento input. Sabemos que e.target se refere ao elemento que disparou o evento. Neste caso, nosso input. Mas o que é o método checkValidity()? Esta é parte da Constraint Validation API. O método checkValidity() retorna true se o elemento corresponder a toda a validação HTML (com base em seus atributos) e false se falhar. Quando tentamos com uma entrada inválida, vemos que false é registrado no console. Agora que sabemos que a entrada é inválida, vamos relatar a invalidade:
<link rel="stylesheet" href="styles.css" />
<form>
  <label>Enter your email: </label>
  <input required placeholder="username@sampleCompany.com" type="email" pattern=".+@sampleCompany\.com" />

  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>

  <button type="submit">Submit Feedback</button>
</form>
<script src="index.js"></script>
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}
const input = document.querySelector("input");

input.addEventListener("input", (e) => {
  if (!e.target.checkValidity()) {
    e.target.reportValidity();
  }
})
E como resultado, você verá a mensagem de erro do navegador "Please match the requested format." Ele reporta o estado inválido imediatamente, em vez de esperar que enviemos o formulário. Mas ainda está usando a mensagem padrão. Isso ocorre porque o método reportValidity apenas informa ao navegador que a entrada é inválida. O navegador ainda escolhe como exibir por que isso é inválido. É aí que o método setCustomValidity entra em ação.
<link rel="stylesheet" href="styles.css" />
<form>
  <label>Enter your email: </label>
  <input required placeholder="username@sampleCompany.com" type="email" pattern=".+@sampleCompany\.com" />

  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>

  <button type="submit">Submit Feedback</button>
</form>
<script src="index.js"></script>
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}
const input = document.querySelector("input");

input.addEventListener("input", (e) => {
  if (!e.target.checkValidity()) {
    e.target.setCustomValidity(
      "You must use a company email address that ends in @sampleCompany.com"
    );
  }
});
Este método aceita uma mensagem de erro personalizada, que é exibida para o usuário. Como resultado, você verá a mensagem de erro personalizada You must use a company email address that ends in @sampleCompany.com. Se você estiver interessado em explorar mais sobre os diferentes tipos de estados de validade e por que uma validação específica falhou, você pode registrar a propriedade validity assim:
<link rel="stylesheet" href="styles.css" />
<form>
  <label>Enter your email: </label>
  <input required placeholder="username@sampleCompany.com" type="email" pattern=".+@sampleCompany\.com" />

  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>

  <button type="submit">Submit Feedback</button>
</form>
<script src="index.js"></script>
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}
const input = document.querySelector("input");

input.addEventListener("input", (e) => {
  console.log(e.target.validity);
})
A propriedade validity é uma instância do objeto ValidityState. Aqui está um exemplo de como o objeto pode parecer no navegador:
ValidityState {
  badInput: false,
  customError: false,
  patternMismatch: true,
  rangeOverflow: false,
  rangeUnderflow: false,
  stepMismatch: false,
  tooLong: false,
  tooShort: false,
  typeMismatch: true,
  valueMissing: false,
  valid: true
}
Existem várias propriedades úteis que todas possuem o valor booleano true ou false. Algumas dessas propriedades úteis que você pode explorar mais por conta própria seriam a propriedade valueMissing que é true quando um campo de entrada obrigatório é deixado vazio. Ou o patternMismatch que é true se o valor não corresponder ao padrão de expressão regular especificado. Após esta lição, incentivo você a experimentar os exemplos fornecidos nesta lição e explorar mais sobre as diferentes propriedades de validade.
Este módulo não possui perguntas. Marque como concluído.