HTML5 Constraint Validation API cung cấp ValidityState object với 2 thuộc tính quan trọng cho input type=number:
- rangeOverflow:
truenếuvalue > max - rangeUnderflow:
truenếuvalue < min
Các thuộc tính khác của validity: valueMissing, typeMismatch, patternMismatch, tooLong, tooShort, stepMismatch, badInput, valid.
Ví dụ minh họa
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Range Overflow/Underflow</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; padding: 20px; }
.result { font-size: 20px; font-weight: 500; margin: 10px 0; color: green; }
input { padding: 8px; font-size: 16px; width: 100px; }
button { padding: 8px 16px; cursor: pointer; font-size: 16px; }
.error { color: red; }
.success { color: green; }
.warning { color: orange; }
</style>
</head>
<body>
<h1>Range Overflow & Underflow Validation</h1>
Nhập số 0-20: <input type="number" id="numInput" min="0" max="20" step="1" />
<button id="checkBtn">KIỂM TRA</button>
<h3> Nhấn nút để kiểm tra số có trong khoảng 0-20 không </h3>
<div class="result" id="result"></div>
<script>
const resEle = document.querySelector("#result");
const numEle = document.querySelector("#numInput");
document.querySelector("#checkBtn").addEventListener("click", () => {
const validity = numEle.validity;
resEle.className = "result"; // Reset class
if (validity.rangeOverflow) {
resEle.innerHTML = '❌ Số vượt quá tối đa (max=20)';
resEle.classList.add('error');
} else if (validity.rangeUnderflow) {
resEle.innerHTML = '❌ Số nhỏ hơn tối thiểu (min=0)';
resEle.classList.add('error');
} else if (validity.stepMismatch) {
resEle.innerHTML = '⚠️ Số không khớp step (step=1)';
resEle.classList.add('warning');
} else if (validity.badInput) {
resEle.innerHTML = '❌ Dữ liệu không phải số hợp lệ';
resEle.classList.add('error');
} else if (validity.valid) {
resEle.innerHTML = '✅ Số nằm trong khoảng cho phép';
resEle.classList.add('success');
} else {
resEle.innerHTML = 'Trạng thái khác: ' + JSON.stringify(validity);
}
// Debug: hiển thị tất cả validity flags
console.log('ValidityState:', validity);
});
// Real-time validation
numEle.addEventListener('input', () => {
numEle.setCustomValidity(''); // Clear custom error
if (numEle.validity.rangeOverflow) {
numEle.setCustomValidity('Số không được lớn hơn 20');
} else if (numEle.validity.rangeUnderflow) {
numEle.setCustomValidity('Số không được nhỏ hơn 0');
}
numEle.reportValidity(); // Show browser native UI
});
</script>
</body>
</html>
Kết quả
- Nhập
25→ ❌ Số vượt quá tối đa (max=20) - Nhập
-5→ ❌ Số nhỏ hơn tối thiểu (min=0) - Nhập
10→ ✅ Số nằm trong khoảng cho phép - Nhập
10.5(step=1) → ⚠️ Số không khớp step
Validation API Methods:
// Kiểm tra form/input hợp lệ
form.checkValidity(); // true/false, không hiển thị UI
form.reportValidity(); // true/false, HIỂN THỊ browser native UI
// Input level
input.checkValidity();
input.reportValidity();
input.setCustomValidity("Custom error message"); // Set custom error
input.validationMessage; // Lấy message hiện tại
CSS Pseudo-classes cho validation:
input:valid { border-color: green; }
input:invalid { border-color: red; }
input:required { /* required fields */ }
input:in-range { /* trong min-max */ }
input:out-of-range { /* ngoài min-max */ }
input:read-only / :read-write { /* readonly state */ }
Tắt validation mặc định browser:
<form novalidate> ... </form>
// Hoặc
input.addEventListener('invalid', e => e.preventDefault());
Lưu ý: Validation API chỉ hoạt động trên <form> và các <input>, <select>, <textarea> có ràng buộc (required, min, max, pattern...).