Validation

Built-in validation with custom rules and error handling

Built-in Validation

Timepicker-UI automatically validates time input and provides feedback for invalid values:

  • Validates time format (HH:mm or hh:mm AM/PM)
  • Checks for valid hour and minute ranges
  • Respects disabled time restrictions
  • Prevents invalid manual input
  • HTML5 time input validation support

Valid Time Detection

Use the accept event to handle valid time selection:

const input = document.querySelector('#timepicker');
const picker = new TimepickerUI(input);
picker.create();
input.addEventListener('accept', (event) => {
const selectedTime = event.detail.hour + ':' + event.detail.minutes;
console.log('Valid time selected:', selectedTime);
// Perform actions with validated time
submitForm(selectedTime);
});

Error Handling

Detect and handle invalid time input:

Invalid Input Detection

const input = document.querySelector('#timepicker');
const errorMessage = document.querySelector('#error-message');
input.addEventListener('input', (e) => {
const value = e.target.value;
if (!isValidTimeFormat(value)) {
errorMessage.textContent = 'Please enter a valid time (HH:mm)';
errorMessage.classList.add('visible');
} else {
errorMessage.classList.remove('visible');
}
});
function isValidTimeFormat(time) {
const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;
return timeRegex.test(time);
}

Disabled Time Validation

const picker = new TimepickerUI(input, {
disabledTime: {
hours: [0, 1, 2, 3, 4, 5, 22, 23]
}
});
picker.create();
input.addEventListener('accept', (event) => {
const hour = event.detail.hour;
// This will never trigger for disabled hours
// as they cannot be selected
console.log('Selected hour:', hour);
});
// Validate manual input
input.addEventListener('change', (e) => {
const [hour] = e.target.value.split(':').map(Number);
const disabledHours = [0, 1, 2, 3, 4, 5, 22, 23];
if (disabledHours.includes(hour)) {
e.target.setCustomValidity('This time is not available');
e.target.reportValidity();
} else {
e.target.setCustomValidity('');
}
});

Custom Validation Rules

Implement custom validation logic for specific business requirements:

Minimum Time Validation

function validateMinTime(selectedTime, minTime) {
const selected = timeToMinutes(selectedTime);
const minimum = timeToMinutes(minTime);
return selected >= minimum;
}
function timeToMinutes(time) {
const [hours, minutes] = time.split(':').map(Number);
return hours * 60 + minutes;
}
// Usage
input.addEventListener('accept', (event) => {
const time = event.detail.hour + ':' + event.detail.minutes;
const minTime = '09:00';
if (!validateMinTime(time, minTime)) {
alert('Please select a time after 9:00 AM');
input.value = '';
}
});

Time Range Validation

function isTimeInRange(time, startTime, endTime) {
const selected = timeToMinutes(time);
const start = timeToMinutes(startTime);
const end = timeToMinutes(endTime);
return selected >= start && selected <= end;
}
function timeToMinutes(time) {
const [hours, minutes] = time.split(':').map(Number);
return hours * 60 + minutes;
}
// Validate on accept
input.addEventListener('accept', (event) => {
const time = event.detail.hour + ':' + event.detail.minutes;
if (!isTimeInRange(time, '09:00', '17:00')) {
showError('Please select a time between 9:00 AM and 5:00 PM');
return;
}
submitTime(time);
});

Date-Time Validation

function validateDateTime(date, time) {
const now = new Date();
const selected = new Date(date + 'T' + time);
return selected > now;
}
// Combined date and time validation
const dateInput = document.querySelector('#date-picker');
const timeInput = document.querySelector('#time-picker');
timeInput.addEventListener('accept', (event) => {
const time = event.detail.hour + ':' + event.detail.minutes;
const date = dateInput.value;
if (!validateDateTime(date, time)) {
showError('Cannot select a time in the past');
timeInput.value = '';
return;
}
console.log('Valid future date-time:', date, time);
});

HTML5 Validation

Leverage native HTML5 validation attributes:

Required Time Input

<form>
<label for="timepicker">
Meeting Time (Required)
</label>
<input
type="time"
id="timepicker"
required
min="09:00"
max="17:00"
step="900"
/>
<button type="submit">Schedule</button>
</form>
<script>
const picker = new TimepickerUI(
document.querySelector('#timepicker')
);
picker.create();
document.querySelector('form').addEventListener('submit', (e) => {
e.preventDefault();
if (e.target.checkValidity()) {
console.log('Form is valid!');
// Submit form
} else {
console.log('Form has validation errors');
}
});
</script>

Custom Validation Messages

const input = document.querySelector('#timepicker');
input.addEventListener('invalid', (e) => {
e.target.setCustomValidity('Please select a valid time');
});
input.addEventListener('input', (e) => {
// Clear custom message when user starts typing
e.target.setCustomValidity('');
});
// Custom range validation
input.addEventListener('change', (e) => {
const [hours, minutes] = e.target.value.split(':').map(Number);
const totalMinutes = hours * 60 + minutes;
if (totalMinutes < 540) { // Before 9:00 AM
e.target.setCustomValidity('Business hours start at 9:00 AM');
e.target.reportValidity();
} else if (totalMinutes > 1020) { // After 5:00 PM
e.target.setCustomValidity('Business hours end at 5:00 PM');
e.target.reportValidity();
} else {
e.target.setCustomValidity('');
}
});

Visual Error States

Style the input to show validation errors:

Error Styling

/* Input error state */
input[type="time"]:invalid {
border-color: #ef4444;
background-color: #fef2f2;
}
input[type="time"]:invalid:focus {
outline-color: #ef4444;
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
}
/* Error message */
.error-message {
display: none;
color: #ef4444;
font-size: 0.875rem;
margin-top: 0.5rem;
}
.error-message.visible {
display: block;
}
/* Success state */
input[type="time"]:valid {
border-color: #10b981;
}

Complete Example

<div class="form-group">
<label for="timepicker">Select Time</label>
<input
type="time"
id="timepicker"
class="form-control"
required
/>
<span class="error-message" id="error"></span>
</div>
<style>
.form-control {
border: 2px solid #e5e7eb;
border-radius: 0.5rem;
padding: 0.5rem 0.75rem;
transition: all 0.2s;
}
.form-control.error {
border-color: #ef4444;
}
.form-control.success {
border-color: #10b981;
}
</style>
<script>
const input = document.querySelector('#timepicker');
const errorMsg = document.querySelector('#error');
input.addEventListener('change', () => {
if (input.validity.valid) {
input.classList.remove('error');
input.classList.add('success');
errorMsg.textContent = '';
} else {
input.classList.add('error');
input.classList.remove('success');
errorMsg.textContent = input.validationMessage;
}
});
</script>

Server-Side Validation

Always validate time values on your server. Client-side validation improves user experience but can be bypassed. Implement the same validation rules on your backend to ensure data integrity and security.

Learn about events