Validɛshɔn fɔ di wok
Gi valyu, akshɔnable fidbak to yu yuza dɛn wit HTML5 fɔm validɛshɔn, tru brawza difɔlt bihayvya ɔ kɔstɔm stayl ɛn JavaSkript.
Aw i de wok
Na so fɔm validɛshɔn de wok wit Bootstrap:
- HTML fɔm validɛshɔn de aplay via CSS in tu pseudo-klas dɛn,
:invalid
ɛn:valid
. I de aplay to<input>
,<select>
, ɛn<textarea>
ɛlimɛnt dɛn. - Bootstrap de skɔp di
:invalid
ɛn:valid
stayl dɛn to mama ɛn papa.was-validated
klas, dɛn kin yuz am fɔ di<form>
. If nɔto dat, ɛni fil we dɛn nid we nɔ gɛt valyu go sho se i nɔ rayt we dɛn de lod di pej. Dis we ya, yu kin pik ustɛm fɔ aktiv dɛn (tipikli afta dɛn dɔn tray fɔ sɛn fɔm). - Fɔ riset di apinɛns fɔ di fɔm (fɔ ɛgzampul, insay di kes fɔ dinamik fɔm sɔbmishɔn dɛn we yu de yuz AJAX), pul di
.was-validated
klas frɔm di<form>
bak afta sɔbmishɔn. - As fɔlbak,
.is-invalid
ɛn.is-valid
klas dɛn kin yuz instead ɔf di pseudo-klas fɔ sava-sayd validɛshɔn . Dɛn nɔ nid fɔ gɛt.was-validated
mama ɛn papa dɛn klas. - Bikɔs ɔf kɔnstrakshɔn dɛn na aw CSS de wok, wi nɔ go ebul (naw) fɔ yuz stayl dɛn to wan
<label>
we de kam bifo wan fɔm kɔntrol na di DOM if dɛn nɔ ɛp di kɔstɔm JavaSkript. - Ɔl di mɔdan brawza dɛn de sɔpɔt di kɔnstrakshɔn validɛshɔn API , we na wan siriɔs JavaSkript we fɔ validet fɔm kɔntrol dɛn.
- Fidbak mɛsej dɛn kin yuz di brɔwza difɔlt dɛn (difrɛn fɔ ɛni brawza, ɛn dɛn nɔ kin stayl am bay CSS) ɔ wi kɔstɔm fidbak stayl dɛn wit ɔda HTML ɛn CSS.
- Yu kin gi kɔstɔm validiti mɛsej dɛn wit
setCustomValidity
insay JavaSkript.
Wit dat in maynd, tink bɔt di demo dɛn we de dɔŋ ya fɔ wi kɔstɔm fɔm validɛshɔn stayl dɛn, opshɔnal sava-sayd klas dɛn, ɛn brawza difɔlt dɛn.
Kastom stayl dɛn
Fɔ kɔstɔm Bootstrap fɔm validɛshɔn mɛsej dɛn, yu go nid fɔ ad di novalidate
buli atribyut to yu <form>
. Dis de mek di brɔwza difɔlt fidbak tultip dɛn nɔ wok, bɔt stil de gi yu akses to di fɔm validɛshɔn API dɛn na JavaSkript. Tray fɔ sɛn di fɔm we de dɔŋ ya; wi JavaSkript go intasept di sɔbmit bɔtin ɛn rilay fidbak to yu. We yu de tray fɔ sɛn, yu go si di :invalid
ɛn :valid
stayl dɛn we dɛn yuz fɔ yu fɔm kɔntrol dɛn.
Kastom fidbak stayl dɛn de yuz kɔstɔm kɔlɔ, bɔda, fɔs stayl, ɛn bakgrɔn aykɔn dɛn fɔ mek dɛn ebul fɔ tɔk bɔt fidbak fayn fayn wan. Bakgrɔn aykɔn fɔ <select>
s de nɔmɔ wit .form-select
, ɛn nɔto .form-control
.
<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)
})
})()
Brawza difɔlt dɛn
Yu nɔ intres pan kɔstɔm validɛshɔn fidbak mɛsej ɔ rayt JavaSkript fɔ chenj fɔm bihayvya? Ɔl gud, yu kin yuz di brɔwza difɔlt dɛn. Tray fɔ sɛn di fɔm we de dɔŋ ya. Dipen pan yu brawza ɛn OS, yu go si difrɛn stayl fɔ fidbak smɔl.
Pan ɔl we dɛn fidbak stayl ya nɔ go ebul fɔ stayl wit CSS, yu kin stil kɔstɔmayz di fidbak tɛks tru JavaSkript.
<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>
Serva sayd
Wi kin advays yu fɔ yuz klaynt-sayd validɛshɔn, bɔt if yu nid fɔ validɛshɔn na di sava-sayd, yu kin sho di fɔm fil dɛn we nɔ valid ɛn we valid wit .is-invalid
ɛn .is-valid
. Notis se .invalid-feedback
dɛn de sɔpɔt bak wit dɛn klas ya.
Fɔ fil dɛn we nɔ rayt, mek shɔ se di fidbak/ɛrɔd mɛsej we nɔ rayt gɛt fɔ du wit di fɔm fil we gɛt fɔ du wit am we yu de yuz aria-describedby
(notis se dis atribyut de alaw id
fɔ rɛfrɛns pas wan, if di fil dɔn ɔlrɛdi pɔynt to ɔda fɔm tɛks).
Fɔ fiks prɔblɛm dɛn wit bɔda rayus , input grup dɛn nid fɔ gɛt ɔda .has-validation
klas.
<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>
Elemɛnt dɛn we dɛn sɔpɔt
Valideshɔn stayl dɛn de fɔ di fɔm kɔntrol ɛn kɔmpɔnɛnt dɛn we de dɔŋ ya:
<input>
s ɛn<textarea>
s wit.form-control
(inklud te to wan.form-control
insay input grup dɛn)<select>
s wit.form-select
.form-check
s
<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>
Tultip dɛn fɔ yuz
If yu fɔm layout alaw am, yu kin swap di .{valid|invalid}-feedback
klas dɛn fɔ .{valid|invalid}-tooltip
klas dɛn fɔ sho validɛshɔn fidbak insay wan stayl tultip. Mek shɔ se yu gɛt mama ɔ papa wit position: relative
pan am fɔ tultip pozishɔn. Insay di ɛgzampul we de dɔŋ ya, wi kɔlɔm klas dɛn dɔn ɔlrɛdi gɛt dis, bɔt yu prɔjek kin nid fɔ gɛt ɔda sɛtup.
<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 bin de
Di tin dɛn we kin chenj
$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>");
Mixin dɛn
Tu miksin dɛn jɔyn togɛda, tru wi lɔp , fɔ jenarayz wi fɔm validɛshɔn fidbak stayl dɛn.
@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;
}
}
}
}
}
Map fɔ di map
Dis na di validɛshɔn Sass map frɔm _variables.scss
. Ɔvarayd ɔ ɛkstɛnd dis fɔ jenarayz difrɛn ɔ ɔda stet dɛn.
$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
)
);
Maps of $form-validation-states
kin gɛt tri opshɔnal paramita fɔ ɔvalayz tultip ɛn fɔs stayl dɛn.
Tay
Used to iterate over $form-validation-states
map values to generate our validation styles. Any modifications to the above Sass map will be reflected in your compiled CSS via this loop.
@each $state, $data in $form-validation-states {
@include form-validation-state($state, $data...);
}
Customizing
Validation states can be customized via Sass with the $form-validation-states
map. Located in our _variables.scss
file, this Sass map is how we generate the default valid
/invalid
validation states. Included is a nested map for customizing each state’s color, icon, tooltip color, and focus shadow. While no other states are supported by browsers, those using custom styles can easily add more complex form feedback.