Compare commits

...
Sign in to create a new pull request.

6 commits

Author SHA1 Message Date
XhmikosR
e4757c708a
Merge branch 'main' into master-ysds-form-validations 2020-06-23 18:36:25 +03:00
Mark Otto
a038d24643 Fix JS linter 2020-06-15 01:14:21 -07:00
Mark Otto
4c53d0b14e Restore missing aria-label, add missing end of file line 2020-06-15 01:10:55 -07:00
ysds
754362ee6b Associate validation feedbacks with their form 2020-06-11 22:40:31 -07:00
ysds
99775f998b Rewrite supported, feedback message and tooltip docs 2020-06-11 22:40:09 -07:00
ysds
a1f6370c61 Drop feedback message by sibling selector 2020-06-11 22:08:28 -07:00
3 changed files with 167 additions and 121 deletions

View file

@ -15,8 +15,6 @@
@mixin form-validation-state($state, $color, $icon) {
.#{$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;
@ -27,7 +25,6 @@
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;
@ -38,13 +35,6 @@
@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;

View file

@ -28,44 +28,32 @@ Here's how form validation works with Bootstrap:
With that in mind, consider the following demos for our custom form validation styles, optional server-side classes, and browser defaults.
## Custom styles
## Form validation styles
For custom Bootstrap form validation messages, you'll need to add the `novalidate` boolean attribute to your `<form>`. This disables the browser default feedback tooltips, but still provides access to the form validation APIs in JavaScript. Try to submit the form below; our JavaScript will intercept the submit button and relay feedback to you. When attempting to submit, you'll see the `:invalid` and `:valid` styles applied to your form controls.
Our form validation styles apply custom colors, borders, focus styles, and background icons to better communicate feedback.
Custom feedback styles apply custom colors, borders, focus styles, and background icons to better communicate feedback. Background icons for `<select>`s are only available with `.form-select`, and not `.form-control`.
For form validation styles, you'll need to add the `novalidate` boolean attribute to your `<form>`. This disables the browser default form validatiom, but still provides access to the form validation APIs in JavaScript. Try to submit the form below, you'll see the `:invalid` and `:valid` styles applied to your form controls. Our JavaScript will intercept the submit button and call the `reportValidity()` method of the form validation API.
{{< example >}}
<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">
<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>
@ -73,16 +61,10 @@ Custom feedback styles apply custom colors, borders, focus styles, and backgroun
<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">
@ -90,9 +72,6 @@ Custom feedback styles apply custom colors, borders, focus styles, and backgroun
<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">
@ -161,40 +140,28 @@ While these feedback styles cannot be styled with CSS, you can still customize t
## Server side
We recommend using client-side validation, but in case you require server-side validation, you can indicate invalid and valid form fields with `.is-invalid` and `.is-valid`. Note that `.invalid-feedback` is also supported with these classes.
We recommend using client-side validation, but in case you require server-side validation, you can indicate invalid and valid form fields with `.is-invalid` and `.is-valid`.
{{< example >}}
<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">
<span class="input-group-text" id="inputGroupPrepend3">@</span>
<input type="text" class="form-control is-invalid" id="validationServerUsername" aria-describedby="inputGroupPrepend3" required>
<div 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" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
<div class="col-md-3">
<label for="validationServer04" class="form-label">State</label>
@ -202,16 +169,10 @@ We recommend using client-side validation, but in case you require server-side v
<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="validationServer05" class="form-label">Zip</label>
<input type="text" class="form-control is-invalid" id="validationServer05" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
<div class="col-12">
<div class="form-check">
@ -219,9 +180,6 @@ We recommend using client-side validation, but in case you require server-side v
<label class="form-check-label" for="invalidCheck3">
Agree to terms and conditions
</label>
<div class="invalid-feedback">
You must agree before submitting.
</div>
</div>
</div>
<div class="col-12">
@ -235,57 +193,131 @@ We recommend using client-side validation, but in case you require server-side v
Validation styles are available for the following form controls and components:
- `<input>`s and `<textarea>`s with `.form-control` (including up to one `.form-control` in input groups)
- `<select>`s with `.form-select`
- `.form-select`s
- `.form-check`s
- `.form-file`
- `.form-file`s
{{< example >}}
<form class="was-validated">
<div class="mb-3">
<label for="validationTextarea" class="form-label">Textarea</label>
<textarea class="form-control is-invalid" id="validationTextarea" placeholder="Required example textarea" required></textarea>
<div class="invalid-feedback">
Please enter a message in the textarea.
<input type="text" class="form-control mb-3" placeholder="Required form control" required>
<textarea class="form-control mb-3" placeholder="Required textarea" required></textarea>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="supportedInputGroupPrepend">@</span>
</div>
<input type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="supportedInputGroupPrepend" required>
</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">
<select class="form-select mb-3" required>
<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 class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="supportedCheckbox" required>
<label class="form-check-label" for="supportedCheckbox">Check this checkbox</label>
</div>
<div class="form-file mb-3">
<input type="file" class="form-file-input" id="validationFormFile" required>
<label class="form-file-label" for="validationFormFile">
<div class="form-check">
<input type="radio" class="form-check-input" id="supportedRadio1" name="radio-supported" required>
<label class="form-check-label" for="supportedRadio1">Toggle this radio</label>
</div>
<div class="form-check mb-3">
<input type="radio" class="form-check-input" id="supportedRadio2" name="radio-supported" required>
<label class="form-check-label" for="supportedRadio2">Or toggle this other radio</label>
</div>
<div class="form-file">
<input type="file" class="form-file-input" id="supportedFormFile" required>
<label class="form-file-label" for="supportedFormFile">
<span class="form-file-text">Choose file...</span>
<span class="form-file-button">Browse</span>
</label>
<div class="invalid-feedback">Example invalid form file feedback</div>
</div>
</form>
{{< /example >}}
## Feedback messages
You can insert custom feedback messages with the `.valid-feedback` or `.invalid-feedback` that replaces the browsers default feedback messages.
{{< example >}}
<form>
<div class="mb-3">
<input type="text" class="form-control is-valid" value="Form control" aria-describedby="messageFeedbackFormControl" required>
<div class="valid-feedback" id="messageFeedbackFormControl">
Example valid feedback text
</div>
</div>
<div class="mb-3">
<button class="btn btn-primary" type="submit" disabled>Submit form</button>
<textarea class="form-control is-valid" aria-describedby="messageFeedbackTextarea" required>Textarea</textarea>
<div class="valid-feedback" id="messageFeedbackTextarea">
Example valid feedback text
</div>
</div>
<div class="mb-3">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="feedbackInputGroupPrepend">@</span>
</div>
<input type="text" class="form-control is-invalid" placeholder="Username" aria-label="Username" aria-describedby="feedbackInputGroupPrepend messageFeedbackInputGroup" required>
</div>
<div class="invalid-feedback" id="messageFeedbackInputGroup">
Example invalid feedback text
</div>
</div>
<div class="mb-3">
<select class="form-select is-invalid" aria-describedby="messageFeedbackSelect" aria-label="Select example" required>
<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" id="messageFeedbackSelect">
Example invalid feedback text
</div>
</div>
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input is-invalid" id="feedbackCheckbox" aria-describedby="messageFeedbackCheckbox" required>
<label class="form-check-label" for="feedbackCheckbox">Check this checkbox</label>
</div>
<div class="invalid-feedback" id="messageFeedbackCheckbox">
Example invalid feedback text
</div>
</div>
<div class="mb-3" aria-describedby="messageFeedbackRadioGroup">
<div class="form-check">
<input type="radio" class="form-check-input is-invalid" id="feedbackRadio1" name="radio-feedback" required>
<label class="form-check-label" for="feedbackRadio1">Toggle this radio</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input is-invalid" id="feedbackRadio2" name="radio-feedback" required>
<label class="form-check-label" for="feedbackRadio2">Or toggle this other radio</label>
</div>
<div class="invalid-feedback" id="messageFeedbackRadioGroup">
Example invalid feedback text
</div>
</div>
<div class="form-file">
<input type="file" class="form-file-input is-invalid" id="feedbackFile" aria-describedby="messageFeedbackFile" required>
<label class="form-file-label" for="feedbackFile">
<span class="form-file-text">Choose file...</span>
<span class="form-file-button">Browse</span>
</label>
</div>
<div class="invalid-feedback" id="messageFeedbackFile">
Example invalid feedback text
</div>
</form>
{{< /example >}}
@ -295,57 +327,80 @@ Validation styles are available for the following form controls and components:
If your form layout allows it, you can swap the `.{valid|invalid}-feedback` classes for `.{valid|invalid}-tooltip` classes to display validation feedback in a styled tooltip. Be sure to have a parent with `position: relative` on it for tooltip positioning. In the example below, our column classes have this already, but your project may require an alternative setup.
{{< example >}}
<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!
<form>
<div class="position-relative mb-5">
<input type="text" class="form-control is-valid" value="Form control" aria-describedby="messageTooltipFormControl" required>
<div class="valid-tooltip" id="messageTooltipFormControl">
Example valid feedback text
</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 class="position-relative mb-5">
<textarea class="form-control is-valid" aria-describedby="messageTooltipTextarea" required>Textarea</textarea>
<div class="valid-tooltip" id="messageTooltipTextarea">
Example valid feedback text
</div>
</div>
<div class="col-md-4 position-relative">
<label for="validationTooltipUsername" class="form-label">Username</label>
<div class="position-relative mb-5">
<div class="input-group">
<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 class="input-group-prepend">
<span class="input-group-text" id="tooltipInputGroupPrepend">@</span>
</div>
<input type="text" class="form-control is-invalid" placeholder="Username" aria-label="Username" aria-describedby="tooltipInputGroupPrepend messageTooltipInputGroup" required>
</div>
<div class="invalid-tooltip" id="messageTooltipInputGroup">
Example invalid feedback text
</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>
<div class="position-relative mb-5">
<select class="form-select is-invalid" aria-describedby="messageTooltipSelect" required>
<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-tooltip">
Please select a valid state.
<div class="invalid-tooltip" id="messageTooltipSelect">
Example invalid feedback text
</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 class="position-relative mb-5">
<div class="form-check">
<input type="checkbox" class="form-check-input is-invalid" id="tooltipCheckbox" aria-describedby="messageTooltipCheckbox" required>
<label class="form-check-label" for="tooltipCheckbox">Check this checkbox</label>
</div>
<div class="invalid-tooltip" id="messageTooltipCheckbox">
Example invalid feedback text
</div>
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit form</button>
<div class="position-relative mb-5" aria-describedby="messageTooltipRadioGroup">
<div class="form-check">
<input type="radio" class="form-check-input is-invalid" id="tooltipRadio1" name="radio-feedback" required>
<label class="form-check-label" for="tooltipRadio1">Toggle this radio</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input is-invalid" id="tooltipRadio2" name="radio-feedback" required>
<label class="form-check-label" for="tooltipRadio2">Or toggle this other radio</label>
</div>
<div class="invalid-tooltip" id="messageTooltipRadioGroup">
Example invalid feedback text
</div>
</div>
<div class="position-relative mb-5">
<div class="form-file">
<input type="file" class="form-file-input is-invalid" id="tooltipFile" aria-describedby="messageTooltipFile" required>
<label class="form-file-label" for="tooltipFile">
<span class="form-file-text">Choose file...</span>
<span class="form-file-button">Browse</span>
</label>
</div>
<div class="invalid-tooltip" id="messageTooltipFile">
Example invalid feedback text
</div>
</div>
</form>
{{< /example >}}

View file

@ -12,6 +12,7 @@
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
form.reportValidity()
}
form.classList.add('was-validated')