Thẩm định
Cung cấp phản hồi hữu ích, có giá trị cho người dùng của bạn với xác thực biểu mẫu HTML5, thông qua các hành vi mặc định của trình duyệt hoặc kiểu tùy chỉnh và JavaScript.
Làm thế nào nó hoạt động
Đây là cách xác thực biểu mẫu hoạt động với Bootstrap:
- Xác thực biểu mẫu HTML được áp dụng thông qua hai lớp giả của CSS
:invalid
và:valid
. Nó áp dụng cho<input>
,<select>
và<textarea>
các phần tử. - Bootstrap mở rộng phạm vi
:invalid
và các:valid
kiểu cho lớp cha.was-validated
, thường được áp dụng cho<form>
. Nếu không, bất kỳ trường bắt buộc nào không có giá trị sẽ hiển thị là không hợp lệ khi tải trang. Bằng cách này, bạn có thể chọn thời điểm kích hoạt chúng (thường là sau khi thử gửi biểu mẫu). - Để đặt lại giao diện của biểu mẫu (ví dụ: trong trường hợp gửi biểu mẫu động bằng AJAX), hãy xóa
.was-validated
lớp khỏi lớp<form>
đó sau khi gửi. - Là một dự phòng
.is-invalid
và.is-valid
các lớp có thể được sử dụng thay vì các lớp giả để xác thực phía máy chủ . Chúng không yêu cầu một.was-validated
lớp cha. - Do những hạn chế về cách hoạt động của CSS, chúng tôi (hiện tại) không thể áp dụng các kiểu cho một
<label>
điều khiển biểu mẫu trong DOM mà không có sự trợ giúp của JavaScript tùy chỉnh. - Tất cả các trình duyệt hiện đại đều hỗ trợ API xác thực ràng buộc , một loạt các phương pháp JavaScript để xác thực các điều khiển biểu mẫu.
- Thông báo phản hồi có thể sử dụng các mặc định của trình duyệt (khác nhau đối với từng trình duyệt và không thể xóa thông qua CSS) hoặc các kiểu phản hồi tùy chỉnh của chúng tôi với HTML và CSS bổ sung.
- Bạn có thể cung cấp thông báo hợp lệ tùy chỉnh bằng
setCustomValidity
JavaScript.
Với ý nghĩ đó, hãy xem xét các bản trình diễn sau cho các kiểu xác thực biểu mẫu tùy chỉnh của chúng tôi, các lớp phía máy chủ tùy chọn và mặc định của trình duyệt.
Phong cách tùy chỉnh
Đối với thông báo xác thực biểu mẫu Bootstrap tùy chỉnh, bạn sẽ cần thêm novalidate
thuộc tính boolean vào của mình <form>
. Thao tác này vô hiệu hóa chú giải công cụ phản hồi mặc định của trình duyệt, nhưng vẫn cung cấp quyền truy cập vào các API xác thực biểu mẫu trong JavaScript. Cố gắng gửi biểu mẫu dưới đây; JavaScript của chúng tôi sẽ chặn nút gửi và chuyển tiếp phản hồi cho bạn. Khi cố gắng gửi, bạn sẽ thấy các kiểu :invalid
và :valid
kiểu được áp dụng cho các điều khiển biểu mẫu của mình.
Kiểu phản hồi tùy chỉnh áp dụng màu tùy chỉnh, đường viền, kiểu tiêu điểm và biểu tượng nền để truyền đạt phản hồi tốt hơn. Biểu tượng nền cho <select>
s chỉ khả dụng với .form-select
và không .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)
})
})()
Mặc định của trình duyệt
Không quan tâm đến thông báo phản hồi xác thực tùy chỉnh hoặc viết JavaScript để thay đổi hành vi của biểu mẫu? Tất cả tốt, bạn có thể sử dụng mặc định của trình duyệt. Hãy thử gửi biểu mẫu bên dưới. Tùy thuộc vào trình duyệt và hệ điều hành của bạn, bạn sẽ thấy một kiểu phản hồi hơi khác nhau.
Mặc dù không thể tạo kiểu cho các kiểu phản hồi này bằng CSS, nhưng bạn vẫn có thể tùy chỉnh văn bản phản hồi thông qua JavaScript.
<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>
Phía máy chủ
Chúng tôi khuyên bạn nên sử dụng xác thực phía máy khách, nhưng trong trường hợp bạn yêu cầu xác thực phía máy chủ, bạn có thể chỉ ra các trường biểu mẫu không hợp lệ và hợp lệ với .is-invalid
và .is-valid
. Lưu ý rằng .invalid-feedback
cũng được hỗ trợ với các lớp này.
Đối với các trường không hợp lệ, hãy đảm bảo rằng thông báo phản hồi / lỗi không hợp lệ được liên kết với trường biểu mẫu có liên quan bằng cách sử dụng aria-describedby
(lưu ý rằng thuộc tính này cho phép nhiều hơn một id
được tham chiếu, trong trường hợp trường đã trỏ đến văn bản biểu mẫu bổ sung).
Để khắc phục sự cố với bán kính đường viền , các nhóm đầu vào yêu cầu một .has-validation
lớp bổ sung.
<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>
Các yếu tố được hỗ trợ
Các kiểu xác thực có sẵn cho các thành phần và điều khiển biểu mẫu sau:
<input>
s và<textarea>
s với.form-control
(bao gồm tối đa một.form-control
trong các nhóm đầu vào)<select>
s với.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>
Chú giải công cụ
Nếu bố cục biểu mẫu của bạn cho phép, bạn có thể hoán đổi các .{valid|invalid}-feedback
lớp cho .{valid|invalid}-tooltip
các lớp để hiển thị phản hồi xác thực trong một chú giải công cụ được tạo kiểu. Đảm bảo có phụ huynh đi cùng position: relative
để định vị chú giải công cụ. Trong ví dụ dưới đây, các lớp cột của chúng tôi đã có điều này, nhưng dự án của bạn có thể yêu cầu thiết lập thay thế.
<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
Biến
$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
Hai mixin được kết hợp với nhau, thông qua vòng lặp của chúng tôi , để tạo ra các kiểu phản hồi xác thực biểu mẫu của chúng tôi.
@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;
}
}
}
}
}
Bản đồ
Đây là bản đồ Sass xác nhận từ _variables.scss
. Ghi đè hoặc mở rộng điều này để tạo ra các trạng thái khác hoặc bổ sung.
$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
)
);
Bản đồ $form-validation-states
có thể chứa ba tham số tùy chọn để ghi đè chú giải công cụ và kiểu tiêu điểm.
Vòng
Được sử dụng để lặp lại $form-validation-states
các giá trị bản đồ nhằm tạo ra các kiểu xác thực của chúng tôi. Bất kỳ sửa đổi nào đối với bản đồ Sass ở trên sẽ được phản ánh trong CSS đã biên dịch của bạn thông qua vòng lặp này.
@each $state, $data in $form-validation-states {
@include form-validation-state($state, $data...);
}
Tùy chỉnh
Trạng thái xác thực có thể được tùy chỉnh thông qua Sass với $form-validation-states
bản đồ. Nằm trong _variables.scss
tệp của chúng tôi, bản đồ Sass này là cách chúng tôi tạo các trạng thái mặc định valid
/ invalid
xác thực. Bao gồm một bản đồ lồng nhau để tùy chỉnh màu sắc, biểu tượng, màu chú giải công cụ và bóng tiêu điểm của từng tiểu bang. Mặc dù không có trạng thái nào khác được trình duyệt hỗ trợ, những người sử dụng kiểu tùy chỉnh có thể dễ dàng thêm phản hồi biểu mẫu phức tạp hơn.