Lumaktaw sa pangunahing nilalaman Lumaktaw sa docs navigation
Check
in English

Pagpapatunay

Magbigay ng mahalaga, naaaksyunan na feedback sa iyong mga user gamit ang HTML5 form validation, sa pamamagitan ng default na gawi ng browser o custom na istilo at JavaScript.

Alam namin na sa kasalukuyan ang mga custom na istilo ng pagpapatunay sa panig ng kliyente at mga tooltip ay hindi naa-access, dahil hindi sila nakalantad sa mga pantulong na teknolohiya. Habang gumagawa kami ng solusyon, inirerekumenda namin ang alinman sa paggamit ng opsyon sa panig ng server o ang default na paraan ng pagpapatunay ng browser.

Paano ito gumagana

Narito kung paano gumagana ang pagpapatunay ng form sa Bootstrap:

  • Ang pagpapatunay ng form ng HTML ay inilalapat sa pamamagitan ng dalawang pseudo-class ng CSS, :invalidat :valid. Nalalapat ito sa <input>, <select>, at <textarea>mga elemento.
  • Sinasaklaw ng Bootstrap ang :invalidat mga :validistilo sa parent .was-validatedclass, karaniwang inilalapat sa <form>. Kung hindi, lalabas ang anumang kinakailangang field na walang value bilang di-wasto sa pag-load ng page. Sa ganitong paraan, maaari mong piliin kung kailan isaaktibo ang mga ito (karaniwang pagkatapos subukan ang pagsusumite ng form).
  • Upang i-reset ang hitsura ng form (halimbawa, sa kaso ng mga dynamic na pagsusumite ng form gamit ang AJAX), alisin ang .was-validatedklase mula sa <form>muli pagkatapos ng pagsusumite.
  • Bilang isang fallback, .is-invalidat .is-validang mga klase ay maaaring gamitin sa halip na ang mga pseudo-class para sa server-side validation . Hindi sila nangangailangan ng .was-validatedklase ng magulang.
  • Dahil sa mga hadlang sa kung paano gumagana ang CSS, hindi namin (sa kasalukuyan) maglapat ng mga istilo sa isang <label>nauuna sa kontrol ng form sa DOM nang walang tulong ng custom na JavaScript.
  • Sinusuportahan ng lahat ng modernong browser ang constraint validation API , isang serye ng mga pamamaraan ng JavaScript para sa pagpapatunay ng mga kontrol sa form.
  • Maaaring gamitin ng mga mensahe ng feedback ang mga default ng browser (iba-iba para sa bawat browser, at hindi mai-istilo sa pamamagitan ng CSS) o ang aming mga custom na istilo ng feedback na may karagdagang HTML at CSS.
  • Maaari kang magbigay ng mga custom na validity na mensahe setCustomValiditysa JavaScript.

Sa pag-iisip na iyon, isaalang-alang ang mga sumusunod na demo para sa aming mga custom na istilo ng pagpapatunay ng form, opsyonal na mga klase sa panig ng server, at mga default ng browser.

Mga custom na istilo

Para sa custom na Bootstrap form validation messages, kakailanganin mong idagdag ang novalidateboolean attribute sa iyong <form>. Hindi nito pinapagana ang default na feedback tooltip ng browser, ngunit nagbibigay pa rin ng access sa mga form validation API sa JavaScript. Subukang isumite ang form sa ibaba; haharangin ng aming JavaScript ang button na isumite at maghahatid ng feedback sa iyo. Kapag sinusubukang isumite, makikita mo ang :invalidat mga :validistilong inilapat sa iyong mga kontrol sa form.

Ang mga custom na istilo ng feedback ay naglalapat ng mga custom na kulay, mga hangganan, mga estilo ng focus, at mga icon sa background upang mas mahusay na makipag-usap ng feedback. Ang mga icon sa background para sa <select>s ay magagamit lamang sa .form-select, at hindi .form-control.

Mukhang maayos!
Mukhang maayos!
@
Mangyaring pumili ng isang username.
Mangyaring magbigay ng wastong lungsod.
Mangyaring pumili ng wastong estado.
Mangyaring magbigay ng wastong zip.
Dapat kang sumang-ayon bago magsumite.
html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-4">
    <label for="validationCustom01" class="form-label">First name</label>
    <input type="text" class="form-control" id="validationCustom01" value="Mark" required>
    <div class="valid-feedback">
      Looks good!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationCustom02" class="form-label">Last name</label>
    <input type="text" class="form-control" id="validationCustom02" value="Otto" required>
    <div class="valid-feedback">
      Looks good!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationCustomUsername" class="form-label">Username</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="inputGroupPrepend">@</span>
      <input type="text" class="form-control" id="validationCustomUsername" aria-describedby="inputGroupPrepend" required>
      <div class="invalid-feedback">
        Please choose a username.
      </div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationCustom03" class="form-label">City</label>
    <input type="text" class="form-control" id="validationCustom03" required>
    <div class="invalid-feedback">
      Please provide a valid city.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationCustom04" class="form-label">State</label>
    <select class="form-select" id="validationCustom04" required>
      <option selected disabled value="">Choose...</option>
      <option>...</option>
    </select>
    <div class="invalid-feedback">
      Please select a valid state.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationCustom05" class="form-label">Zip</label>
    <input type="text" class="form-control" id="validationCustom05" required>
    <div class="invalid-feedback">
      Please provide a valid zip.
    </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">
        Agree to terms and conditions
      </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 form</button>
  </div>
</form>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(() => {
  'use strict'

  // Fetch all the forms we want to apply custom Bootstrap validation styles to
  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)
  })
})()

Mga default ng browser

Hindi interesado sa mga mensahe ng feedback sa custom na pagpapatunay o pagsulat ng JavaScript upang baguhin ang mga gawi ng form? Lahat ng mabuti, maaari mong gamitin ang mga default ng browser. Subukang isumite ang form sa ibaba. Depende sa iyong browser at OS, makakakita ka ng bahagyang naiibang istilo ng feedback.

Bagama't hindi mai-istilo ang mga istilo ng feedback na ito gamit ang CSS, maaari mo pa ring i-customize ang text ng feedback sa pamamagitan ng JavaScript.

@
html
<form class="row g-3">
  <div class="col-md-4">
    <label for="validationDefault01" class="form-label">First name</label>
    <input type="text" class="form-control" id="validationDefault01" value="Mark" required>
  </div>
  <div class="col-md-4">
    <label for="validationDefault02" class="form-label">Last name</label>
    <input type="text" class="form-control" id="validationDefault02" value="Otto" required>
  </div>
  <div class="col-md-4">
    <label for="validationDefaultUsername" class="form-label">Username</label>
    <div class="input-group">
      <span class="input-group-text" id="inputGroupPrepend2">@</span>
      <input type="text" class="form-control" id="validationDefaultUsername"  aria-describedby="inputGroupPrepend2" required>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationDefault03" class="form-label">City</label>
    <input type="text" class="form-control" id="validationDefault03" required>
  </div>
  <div class="col-md-3">
    <label for="validationDefault04" class="form-label">State</label>
    <select class="form-select" id="validationDefault04" required>
      <option selected disabled value="">Choose...</option>
      <option>...</option>
    </select>
  </div>
  <div class="col-md-3">
    <label for="validationDefault05" class="form-label">Zip</label>
    <input type="text" class="form-control" id="validationDefault05" required>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" value="" id="invalidCheck2" required>
      <label class="form-check-label" for="invalidCheck2">
        Agree to terms and conditions
      </label>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit form</button>
  </div>
</form>

Sa panig ng server

Inirerekomenda namin ang paggamit ng pagpapatunay sa panig ng kliyente, ngunit kung sakaling kailanganin mo ang pagpapatunay sa panig ng server, maaari mong isaad ang mga di-wasto at wastong mga field ng form na may .is-invalidat .is-valid. Tandaan na .invalid-feedbacksinusuportahan din sa mga klase na ito.

Para sa mga di-wastong field, tiyaking nauugnay ang invalid na mensahe ng feedback/error sa may-katuturang field ng form gamit aria-describedbyang (na binabanggit na ang katangiang ito ay nagbibigay-daan sa higit sa isa idna ma-reference, kung sakaling tumuturo na ang field sa karagdagang text ng form).

Upang ayusin ang mga isyu sa border radius , ang mga input group ay nangangailangan ng karagdagang .has-validationklase.

Mukhang maayos!
Mukhang maayos!
@
Mangyaring pumili ng isang username.
Mangyaring magbigay ng wastong lungsod.
Mangyaring pumili ng wastong estado.
Mangyaring magbigay ng wastong zip.
Dapat kang sumang-ayon bago magsumite.
html
<form class="row g-3">
  <div class="col-md-4">
    <label for="validationServer01" class="form-label">First name</label>
    <input type="text" class="form-control is-valid" id="validationServer01" value="Mark" required>
    <div class="valid-feedback">
      Looks good!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationServer02" class="form-label">Last name</label>
    <input type="text" class="form-control is-valid" id="validationServer02" value="Otto" required>
    <div class="valid-feedback">
      Looks good!
    </div>
  </div>
  <div class="col-md-4">
    <label for="validationServerUsername" class="form-label">Username</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="inputGroupPrepend3">@</span>
      <input type="text" class="form-control is-invalid" id="validationServerUsername" aria-describedby="inputGroupPrepend3 validationServerUsernameFeedback" required>
      <div id="validationServerUsernameFeedback" class="invalid-feedback">
        Please choose a username.
      </div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationServer03" class="form-label">City</label>
    <input type="text" class="form-control is-invalid" id="validationServer03" aria-describedby="validationServer03Feedback" required>
    <div id="validationServer03Feedback" class="invalid-feedback">
      Please provide a valid city.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationServer04" class="form-label">State</label>
    <select class="form-select is-invalid" id="validationServer04" aria-describedby="validationServer04Feedback" required>
      <option selected disabled value="">Choose...</option>
      <option>...</option>
    </select>
    <div id="validationServer04Feedback" class="invalid-feedback">
      Please select a valid state.
    </div>
  </div>
  <div class="col-md-3">
    <label for="validationServer05" class="form-label">Zip</label>
    <input type="text" class="form-control is-invalid" id="validationServer05" aria-describedby="validationServer05Feedback" required>
    <div id="validationServer05Feedback" class="invalid-feedback">
      Please provide a valid zip.
    </div>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input is-invalid" type="checkbox" value="" id="invalidCheck3" aria-describedby="invalidCheck3Feedback" required>
      <label class="form-check-label" for="invalidCheck3">
        Agree to terms and conditions
      </label>
      <div id="invalidCheck3Feedback" class="invalid-feedback">
        You must agree before submitting.
      </div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit form</button>
  </div>
</form>

Mga sinusuportahang elemento

Available ang mga istilo ng pagpapatunay para sa mga sumusunod na kontrol at bahagi ng form:

  • <input>s at <textarea>s na may .form-control(kabilang ang hanggang isa .form-controlsa mga pangkat ng input)
  • <select>s kasama.form-select
  • .form-checks
Mangyaring magpasok ng mensahe sa textarea.
Halimbawa ng di-wastong text ng feedback
Higit pang halimbawa ng di-wastong text ng feedback
Halimbawa di-wastong pagpili ng feedback
Halimbawa ng di-wastong feedback ng form file
html
<form class="was-validated">
  <div class="mb-3">
    <label for="validationTextarea" class="form-label">Textarea</label>
    <textarea class="form-control" id="validationTextarea" placeholder="Required example textarea" required></textarea>
    <div class="invalid-feedback">
      Please enter a message in the textarea.
    </div>
  </div>

  <div class="form-check mb-3">
    <input type="checkbox" class="form-check-input" id="validationFormCheck1" required>
    <label class="form-check-label" for="validationFormCheck1">Check this checkbox</label>
    <div class="invalid-feedback">Example invalid feedback text</div>
  </div>

  <div class="form-check">
    <input type="radio" class="form-check-input" id="validationFormCheck2" name="radio-stacked" required>
    <label class="form-check-label" for="validationFormCheck2">Toggle this radio</label>
  </div>
  <div class="form-check mb-3">
    <input type="radio" class="form-check-input" id="validationFormCheck3" name="radio-stacked" required>
    <label class="form-check-label" for="validationFormCheck3">Or toggle this other radio</label>
    <div class="invalid-feedback">More example invalid feedback text</div>
  </div>

  <div class="mb-3">
    <select class="form-select" required aria-label="select example">
      <option value="">Open this select menu</option>
      <option value="1">One</option>
      <option value="2">Two</option>
      <option value="3">Three</option>
    </select>
    <div class="invalid-feedback">Example invalid select feedback</div>
  </div>

  <div class="mb-3">
    <input type="file" class="form-control" aria-label="file example" required>
    <div class="invalid-feedback">Example invalid form file feedback</div>
  </div>

  <div class="mb-3">
    <button class="btn btn-primary" type="submit" disabled>Submit form</button>
  </div>
</form>

Mga tooltip

Kung pinapayagan ito ng iyong layout ng form, maaari mong palitan ang mga .{valid|invalid}-feedbackklase para sa mga .{valid|invalid}-tooltipklase upang magpakita ng feedback sa pagpapatunay sa isang naka-istilong tooltip. Tiyaking may kasamang magulang position: relativepara sa pagpoposisyon ng tooltip. Sa halimbawa sa ibaba, mayroon na nito ang aming mga klase sa column, ngunit maaaring mangailangan ng alternatibong setup ang iyong proyekto.

Mukhang maayos!
Mukhang maayos!
@
Mangyaring pumili ng natatangi at wastong username.
Mangyaring magbigay ng wastong lungsod.
Mangyaring pumili ng wastong estado.
Mangyaring magbigay ng wastong zip.
html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-4 position-relative">
    <label for="validationTooltip01" class="form-label">First name</label>
    <input type="text" class="form-control" id="validationTooltip01" value="Mark" required>
    <div class="valid-tooltip">
      Looks good!
    </div>
  </div>
  <div class="col-md-4 position-relative">
    <label for="validationTooltip02" class="form-label">Last name</label>
    <input type="text" class="form-control" id="validationTooltip02" value="Otto" required>
    <div class="valid-tooltip">
      Looks good!
    </div>
  </div>
  <div class="col-md-4 position-relative">
    <label for="validationTooltipUsername" class="form-label">Username</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="validationTooltipUsernamePrepend">@</span>
      <input type="text" class="form-control" id="validationTooltipUsername" aria-describedby="validationTooltipUsernamePrepend" required>
      <div class="invalid-tooltip">
        Please choose a unique and valid username.
      </div>
    </div>
  </div>
  <div class="col-md-6 position-relative">
    <label for="validationTooltip03" class="form-label">City</label>
    <input type="text" class="form-control" id="validationTooltip03" required>
    <div class="invalid-tooltip">
      Please provide a valid city.
    </div>
  </div>
  <div class="col-md-3 position-relative">
    <label for="validationTooltip04" class="form-label">State</label>
    <select class="form-select" id="validationTooltip04" required>
      <option selected disabled value="">Choose...</option>
      <option>...</option>
    </select>
    <div class="invalid-tooltip">
      Please select a valid state.
    </div>
  </div>
  <div class="col-md-3 position-relative">
    <label for="validationTooltip05" class="form-label">Zip</label>
    <input type="text" class="form-control" id="validationTooltip05" required>
    <div class="invalid-tooltip">
      Please provide a valid zip.
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit form</button>
  </div>
</form>

Sass

Mga variable

$form-feedback-margin-top:          $form-text-margin-top;
$form-feedback-font-size:           $form-text-font-size;
$form-feedback-font-style:          $form-text-font-style;
$form-feedback-valid-color:         $success;
$form-feedback-invalid-color:       $danger;

$form-feedback-icon-valid-color:    $form-feedback-valid-color;
$form-feedback-icon-valid:          url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>");
$form-feedback-icon-invalid-color:  $form-feedback-invalid-color;
$form-feedback-icon-invalid:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='#{$form-feedback-icon-invalid-color}'><circle cx='6' cy='6' r='4.5'/><path stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/><circle cx='6' cy='8.2' r='.6' fill='#{$form-feedback-icon-invalid-color}' stroke='none'/></svg>");

Mixins

Dalawang mixin ang pinagsama-sama, sa pamamagitan ng aming loop , upang bumuo ng aming mga istilo ng feedback sa pagpapatunay ng form.

@mixin form-validation-state-selector($state) {
  @if ($state == "valid" or $state == "invalid") {
    .was-validated #{if(&, "&", "")}:#{$state},
    #{if(&, "&", "")}.is-#{$state} {
      @content;
    }
  } @else {
    #{if(&, "&", "")}.is-#{$state} {
      @content;
    }
  }
}

@mixin form-validation-state(
  $state,
  $color,
  $icon,
  $tooltip-color: color-contrast($color),
  $tooltip-bg-color: rgba($color, $form-feedback-tooltip-opacity),
  $focus-box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba($color, $input-btn-focus-color-opacity)
) {
  .#{$state}-feedback {
    display: none;
    width: 100%;
    margin-top: $form-feedback-margin-top;
    @include font-size($form-feedback-font-size);
    font-style: $form-feedback-font-style;
    color: $color;
  }

  .#{$state}-tooltip {
    position: absolute;
    top: 100%;
    z-index: 5;
    display: none;
    max-width: 100%; // Contain to parent when possible
    padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;
    margin-top: .1rem;
    @include font-size($form-feedback-tooltip-font-size);
    line-height: $form-feedback-tooltip-line-height;
    color: $tooltip-color;
    background-color: $tooltip-bg-color;
    @include border-radius($form-feedback-tooltip-border-radius);
  }

  @include form-validation-state-selector($state) {
    ~ .#{$state}-feedback,
    ~ .#{$state}-tooltip {
      display: block;
    }
  }

  .form-control {
    @include form-validation-state-selector($state) {
      border-color: $color;

      @if $enable-validation-icons {
        padding-right: $input-height-inner;
        background-image: escape-svg($icon);
        background-repeat: no-repeat;
        background-position: right $input-height-inner-quarter center;
        background-size: $input-height-inner-half $input-height-inner-half;
      }

      &:focus {
        border-color: $color;
        box-shadow: $focus-box-shadow;
      }
    }
  }

  // stylelint-disable-next-line selector-no-qualifying-type
  textarea.form-control {
    @include form-validation-state-selector($state) {
      @if $enable-validation-icons {
        padding-right: $input-height-inner;
        background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
      }
    }
  }

  .form-select {
    @include form-validation-state-selector($state) {
      border-color: $color;

      @if $enable-validation-icons {
        &:not([multiple]):not([size]),
        &:not([multiple])[size="1"] {
          padding-right: $form-select-feedback-icon-padding-end;
          background-image: escape-svg($form-select-indicator), escape-svg($icon);
          background-position: $form-select-bg-position, $form-select-feedback-icon-position;
          background-size: $form-select-bg-size, $form-select-feedback-icon-size;
        }
      }

      &:focus {
        border-color: $color;
        box-shadow: $focus-box-shadow;
      }
    }
  }

  .form-control-color {
    @include form-validation-state-selector($state) {
      @if $enable-validation-icons {
        width: add($form-color-width, $input-height-inner);
      }
    }
  }

  .form-check-input {
    @include form-validation-state-selector($state) {
      border-color: $color;

      &:checked {
        background-color: $color;
      }

      &:focus {
        box-shadow: $focus-box-shadow;
      }

      ~ .form-check-label {
        color: $color;
      }
    }
  }
  .form-check-inline .form-check-input {
    ~ .#{$state}-feedback {
      margin-left: .5em;
    }
  }

  .input-group {
    > .form-control:not(:focus),
    > .form-select:not(:focus),
    > .form-floating:not(:focus-within) {
      @include form-validation-state-selector($state) {
        @if $state == "valid" {
          z-index: 3;
        } @else if $state == "invalid" {
          z-index: 4;
        }
      }
    }
  }
}

Mapa

Ito ang pagpapatunay na mapa ng Sass mula sa _variables.scss. I-override o palawigin ito upang makabuo ng iba o karagdagang mga estado.

$form-validation-states: (
  "valid": (
    "color": $form-feedback-valid-color,
    "icon": $form-feedback-icon-valid
  ),
  "invalid": (
    "color": $form-feedback-invalid-color,
    "icon": $form-feedback-icon-invalid
  )
);

Ang mga mapa ng $form-validation-statesay maaaring maglaman ng tatlong opsyonal na parameter upang i-override ang mga tooltip at mga estilo ng pagtutok.

Loop

Ginagamit upang umulit sa mga $form-validation-stateshalaga ng mapa upang mabuo ang aming mga istilo ng pagpapatunay. Ang anumang mga pagbabago sa nasa itaas na mapa ng Sass ay makikita sa iyong pinagsama-samang CSS sa pamamagitan ng loop na ito.

@each $state, $data in $form-validation-states {
  @include form-validation-state($state, $data...);
}

Pagpapasadya

Maaaring i-customize ang mga estado ng pagpapatunay sa pamamagitan ng Sass gamit ang $form-validation-statesmapa. Matatagpuan sa aming _variables.scssfile, ang mapa ng Sass na ito ay kung paano namin nabuo ang mga estado ng default valid/ invalidvalidation. Kasama ang isang nested na mapa para sa pag-customize ng kulay, icon, kulay ng tooltip, at focus shadow ng bawat estado. Bagama't walang ibang mga estado ang sinusuportahan ng mga browser, ang mga gumagamit ng mga custom na istilo ay madaling magdagdag ng mas kumplikadong feedback sa form.