Bootstrap 表单验证怎么实现?

文章导读
上一个 测验 下一个 本章将讨论 Bootstrap 验证。Bootstrap 5 Validation 通过为用户提供有用的反馈来增强 HTML5 表单验证,支持默认浏览器行为、自定义样式和 JavaScript。
📋 目录
  1. 自定义样式
  2. 浏览器默认样式
  3. 服务端
  4. 支持的元素
  5. 工具提示
A A

Bootstrap - 验证



上一个
测验
下一个

本章将讨论 Bootstrap 验证。Bootstrap 5 Validation 通过为用户提供有用的反馈来增强 HTML5 表单验证,支持默认浏览器行为、自定义样式和 JavaScript。

客户端自定义验证样式和工具提示不可访问,因为它们对辅助技术不可见。 建议使用服务器端选项或默认浏览器验证技术,同时我们正在研究解决方案。

Bootstrap 中表单验证的工作原理

  • CSS 中的两个伪类 :invalid:valid 用于提供 HTML 表单验证。它适用于 <textarea><select><input> 元素。

  • Bootstrap 将 :invalid:valid 样式应用到父级 .was-validated class 上。页面加载时没有值的字段会显示为无效状态。你可以选择何时激活它们(通常在表单提交后)。

  • 使用 Ajax 进行动态提交后,要恢复表单的原始外观,应从 <form> 中移除 .was-validated class 以重置其外观。

  • 对于服务器端验证,可以使用 .is-invalid.is-valid class 作为后备方案,无需 .was-validated 父级 class。

  • 目前,由于 CSS 限制,我们无法在没有自定义 JavaScript 帮助的情况下直接将样式应用到 DOM 中紧随表单控件之前的 <label> 元素。

  • 所有现代 Web 浏览器都支持 constraint validation API,该 API 包含各种用于验证表单控件的 JavaScript 方法。

  • 使用浏览器默认样式,或使用 HTML/CSS 创建自定义反馈样式。

  • 使用 JavaScript 中的 setCustomValidity 方法来设置独特的有效性消息。

让我们来看一些自定义表单验证样式、可选服务器端 class 和浏览器默认的示例。

自定义样式

  • <form> 上添加 novalidate 布尔属性,以从 Bootstrap 接收自定义验证消息。

  • 上述布尔属性会禁用浏览器默认的反馈工具提示,但 JavaScript validation APIs 仍然有效。提交此表单将触发 JavaScript 提供反馈,在表单控件上显示 :invalid:valid 样式。

  • 自定义反馈样式通过添加颜色、边框、焦点样式和背景图标来改善反馈沟通。对于 <select> 的背景图标仅适用于 .form-select,而不适用于 .form-control

此示例演示了一个带有验证功能的 Bootstrap 表单,以确保在表单提交前必填字段被正确填写。

示例

您可以使用 Edit & Run 选项编辑并尝试运行此代码。

  <!DOCTYPE html>
  <html lang="en">
  <head>
   <title>Bootstrap - Validation</title>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
   <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
   <form class="row g-3 needs-validation" novalidate>
     <div class="col-md-4">
       <label for="validationCustomName" class="form-label">Full Name</label>
       <input type="text" class="form-control" id="validationCustomName" value="Jhon Miller" required>
       <div class="invalid-feedback">
           Correct input!
       </div>
     </div>

     <div class="col-md-4">
       <label for="validationCustomEmail" class="form-label">Email Id</label>
       <div class="input-group has-validation">
         <input type="text" class="form-control" id="validationCustomEmail" aria-describedby="inputGroupPrepend" required>
         <span class="input-group-text" id="inputGroupPrepend">@example.com</span>
         <div class="invalid-feedback">
            Please enter correct mail id.
         </div>
       </div>
     </div>

     <div class="col-md-4">
       <label for="validationCustomPhone" class="form-label">Mobile no</label>
       <input type="text" class="form-control" id="validationCustomPhone" required>
       <div class="invalid-feedback">
          please enter correct mobile no.
       </div>
     </div>

     <div class="col-md-6">
       <label for="validationAddress" class="form-label">Address</label>
         <input type="text" class="form-control" id="validationAddress" value="XYZ - 123" required>
         <div class="valid-feedback">
          Correct input!
         </div>
       </div>
     </div>

     <div class="col-md-3">
       <label for="validationCustom" class="form-label">Gender</label>
       <select class="form-select" id="validationCustom" required>
         <option selected disabled value="">Choose...</option>
         <option>Male</option>
         <option>Female</option>
         <option>Others</option>
       </select>
       <div class="invalid-feedback">
          Please select gender.
       </div>
     </div>

     <div class="col-12">
       <div class="form-check">
         <input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>
         <label class="form-check-label" for="invalidCheck">
            I have reviewed and agree to Terms of Services and Privacy Policy.
         </label>
         <div class="invalid-feedback">
            You must agree before submitting.
         </div>
       </div>
     </div>

     <div class="col-12">
       <button class="btn btn-primary" type="submit">Submit</button>
     </div>
   </form>
  <script>
    (() => {
    'use strict'

    // Fetch all the forms we want to apply custom Bootstrap validation styles to
    // 获取所有我们想要应用自定义 Bootstrap 验证样式的表单
    const forms = document.querySelectorAll('.needs-validation')

    // Loop over them and prevent submission
    // 遍历它们并阻止提交
    Array.from(forms).forEach(form => {
      form.addEventListener('submit', event => {
        if (!form.checkValidity()) {
          event.preventDefault()
          event.stopPropagation()
        }

        form.classList.add('was-validated')
      }, false)
    })
  })()
  </script>
  </body>
  </html>

以下 JavaScript 代码片段会在存在无效字段时禁用表单提交。它通过为表单添加事件监听器,并在表单无效时阻止默认表单提交行为来实现这一点。


    // Example JavaScript starter for disabling form submissions if there are invalid fields
    // 示例 JavaScript 代码,用于在存在无效字段时禁用表单提交
    (() => {
      'use strict'

      // Fetch all the forms we want to apply custom Bootstrap validation styles to
      // 获取所有我们想要应用自定义 Bootstrap 验证样式的表单
      const forms = document.querySelectorAll('.needs-validation')

      // Loop over them and prevent submission
      // 遍历它们并阻止提交
      Array.from(forms).forEach(form => {
        form.addEventListener('submit', event => {
          if (!form.checkValidity()) {
            event.preventDefault()
            event.stopPropagation()
          }

          form.classList.add('was-validated')
        }, false)
      })
    })()

浏览器默认样式

  • 我们也可以使用浏览器默认消息而不是自定义验证消息。根据你的浏览器和操作系统,反馈样式会有所不同。

  • 虽然 CSS 无法用来样式化这些反馈样式,但 JavaScript 仍然可以用来更改反馈文本。

尝试提交以下示例中的表单,查看浏览器默认验证消息是如何显示的。

示例

你可以使用 Edit & Run 选项来编辑并运行这段代码。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>Bootstrap Form - Validation</title>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
    </head>
    <body>
      <form class="row g-3">
        <div class="col-md-4">
          <label for="validationDefaultName" class="form-label">Full Name</label>
          <input type="text" class="form-control" id="validationDefaultName" value="name" required>
        </div>
        <div class="col-md-4">
          <label for="validationDefaultEmail" class="form-label">Email Id</label>
          <div class="input-group">
            <input type="text" class="form-control" id="validationDefaultEmail" aria-describedby="inputGroupPrepend" required>
            <span class="input-group-text" id="inputGroupPrepend">@example.com</span>
          </div>
        </div>
        <div class="col-md-4">
          <label for="validationDefaultMob" class="form-label">Mobile No</label>
          <input type="text" class="form-control" id="validationDefaultMob" value="" required>
        </div>
        <div class="col-md-6">
          <label for="validationDefaultAddress" class="form-label">Address</label>
          <input type="text" class="form-control" id="validationDefaultAddress" required>
        </div>
        <div class="col-md-3">
          <label for="validationDefaultGender" class="form-label">Gender</label>
          <select class="form-select" id="validationDefaultGender" required>
            <option selected disabled value="">Choose...</option>
            <option>Male</option>
            <option>Female</option>
            <option>Others</option>
          </select>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" value="" id="invalidCheck2" required>
            <label class="form-check-label" for="invalidCheck2">
              I have reviewed and agree to Terms of Services and Privacy Policy.
            </label>
          </div>
        </div>
        <div class="col-12">
          <button class="btn btn-primary" type="submit">Submit</button>
        </div>
      </form>
    </body>
    </html>

服务端

  • 推荐使用客户端验证,但在服务端验证的情况下,使用 .is-invalid.is-valid 类来指示表单字段状态。同时考虑与这些类一起使用 .invalid-feedback

  • 对于无效字段,使用 aria-describedby 属性将无效反馈/错误消息链接到表单字段。(如果字段连接到其他表单文本,可以引用多个 id。)

  • 输入组需要额外的 .has-validation 类来处理边框半径问题。

示例

您可以使用 Edit & Run 选项编辑并尝试运行此代码。

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <title>Bootstrap - Validation</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <form class="row g-3">
      <div class="col-md-4">
        <label for="validationServerName" class="form-label">Full name</label>
        <input type="text" class="form-control is-valid" id="validationServerName" value="Mark" required>
        <div class="valid-feedback">
          enter your name
        </div>
      </div>
      <div class="col-md-4">
        <label for="validationServerEmail" class="form-label">Email Id</label>
        <div class="input-group has-validation">
          <input type="text" class="form-control is-invalid" id="validationServerEmail"
            aria-describedby="inputGroupPrepend3 validationServerEmailFeedback" required>
          <span class="input-group-text" id="inputGroupPrepend3">@example.com</span>
          <div id="validationServerEmailFeedback" class="invalid-feedback">
            Please enter mail id.
          </div>
        </div>
      </div>
      <div class="col-md-4">
        <label for="validationServerMob" class="form-label">Mobile no</label>
        <input type="text" class="form-control is-valid" id="validationServerMob" value="" required>
        <div class="valid-feedback">
          Please enter mobile no
        </div>
      </div>
      <div class="col-md-6">
        <label for="validationServerAddress" class="form-label">Address</label>
        <input type="text" class="form-control is-invalid" id="validationServerAddress"
          aria-describedby="validationServerAddressFeedback" required>
        <div id="validationServerAddressFeedback" class="invalid-feedback">
          Please enter a valid Address.
        </div>
      </div>
      <div class="col-md-3">
        <label for="validationServer04" class="form-label">Gender</label>
        <select class="form-select is-invalid" id="validationServer04" aria-describedby="validationServer04Feedback"
          required>
          <option selected disabled value="">Choose...</option>
          <option>Male</option>
          <option>Female</option>
          <option>Others</option>
        </select>
        <div id="validationServer04Feedback" class="invalid-feedback">
          Please select a valid gender.
        </div>
      </div>
      <div class="col-12">
        <div class="form-check">
          <input class="form-check-input is-invalid" type="checkbox" value="" id="invalidCheckPolicy"
            aria-describedby="invalidCheckFeedback" required>
          <label class="form-check-label" for="invalidCheckPolicy">
            I have reviewed and agree to Terms of Services and Privacy Policy.
          </label>
          <div id="invalidCheckFeedback" class="invalid-feedback">
            You must agree before submitting.
          </div>
        </div>
      </div>
      <div class="col-12">
        <button class="btn btn-primary" type="submit">Submit</button>
      </div>
    </form>
  </body>
  </html>;

支持的元素

以下表单控件和组件支持验证样式:

  • <textarea><input> 使用 .form-control(允许 input group 包含最多一个 .form-control)。

  • <select> 使用 .form-select

  • .form-check

示例

您可以使用 Edit & Run 选项编辑并尝试运行此代码。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>Bootstrap Form - Validation</title>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
    </head>
    <body>
      <form class="was-validated">
        <div class="mb-3">
          <label for="validationTextarea" class="form-label">添加评论</label>
          <textarea class="form-control" id="validationTextarea" placeholder="在此输入评论" required></textarea>
          <div class="invalid-feedback">
            添加评论
          </div>
        </div>
        <div class="form-check mb-3">
          <input type="checkbox" class="form-check-input" id="validationFormCheck" required>
          <label class="form-check-label" for="validationFormCheck">项目一</label>
          <div class="invalid-feedback">无效答案</div>
        </div>
        <div class="form-check">
          <input type="radio" class="form-check-input" id="validationFormRadio1" name="radio-stacked" required>
          <label class="form-check-label" for="validationFormRadio1">项目二</label>
        </div>
        <div class="form-check mb-3">
          <input type="radio" class="form-check-input" id="validationFormRadio2" name="radio-stacked" required>
          <label class="form-check-label" for="validationFormRadio2">项目三</label>
          <div class="invalid-feedback">无效答案</div>
        </div>
        <div class="mb-3">
          <select class="form-select" required aria-label="select example">
            <option value="">性别</option>
            <option value="1">男</option>
            <option value="2">女</option>
            <option value="3">其他</option>
          </select>
          <div class="invalid-feedback">无效选择</div>
        </div>
        <div class="mb-3">
          <input type="file" class="form-control" aria-label="file example" required>
          <div class="invalid-feedback">文件大小超过 256kb</div>
        </div>
        <div class="mb-3">
          <button class="btn btn-primary" type="submit" disabled>提交</button>
        </div>
      </form>
    </body>
    </html>

工具提示

  • 要在样式化的工具提示中显示验证反馈,如果布局允许,可以将类 .{valid|invalid}-feedback 替换为 .{valid|invalid}-tooltip

  • 要定位工具提示,请确保父元素具有 position: relative 属性。

示例

您可以使用 Edit & Run 选项来编辑并尝试运行此代码。

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <title>Bootstrap - Validation</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <form class="row g-3 needs-validation" novalidate>
      <div class="col-md-4 position-relative">
        <label for="validationTooltipName" class="form-label">Full Name</label>
        <input type="text" class="form-control" id="validationTooltipName" value="Jhon Miller" required>
        <div class="valid-tooltip">
          Correct Input!
        </div>
      </div>
      <div class="col-md-4 position-relative">
        <label for="validationTooltipEmail" class="form-label">Email Id</label>
        <div class="input-group has-validation">
          <input type="text" class="form-control" id="validationTooltipEmail" aria-describedby="validationTooltipEmailPrepend" required>
          <span class="input-group-text" id="validationTooltipEmailPrepend">@example.com</span>
          <div class="invalid-tooltip">
           Please enter mail id.
          </div>
        </div>
      </div>
      <div class="col-md-4 position-relative">
        <label for="validationTooltipMob" class="form-label">Mobile no</label>
        <input type="text" class="form-control" id="validationTooltipMob" required>
        <div class="invalid-tooltip">
          Please enter mobile no.
        </div>
      </div>

      <div class="col-md-6 position-relative">
        <label for="validationTooltipAddress" class="form-label">Address</label>
        <input type="text" class="form-control" id="validationTooltipAddress" value="XYZ - 123" required>
        <div class="valid-tooltip">
         Correct Input!
        </div>
      </div>
      <div class="col-md-3 position-relative">
        <label for="validationTooltip04" class="form-label">Gender</label>
        <select class="form-select" id="validationTooltip04" required>
          <option selected disabled value="">Choose...</option>
          <option>Male</option>
          <option>Female</option>
          <option>Others</option>
        </select>
        <div class="invalid-tooltip">
          Please select a valid gender.
        </div>
      </div>

      </div>
      <div class="col-12">
        <button class="btn btn-primary" type="submit">Submit</button>
      </div>
    </form>
    <script>
      (() => {
    'use strict'

    // 获取所有需要应用自定义 Bootstrap 验证样式的表单
    const forms = document.querySelectorAll('.needs-validation')

    // 遍历它们并阻止提交
    Array.from(forms).forEach(form => {
      form.addEventListener('submit', event => {
        if (!form.checkValidity()) {
          event.preventDefault()
          event.stopPropagation()
        }

        form.classList.add('was-validated')
      }, false)
    })
  })()
    </script>
  </body>
  </html>