When Should We Come?
A booking without a date is useless. Customers need to pick when they want their service. HTML’s native date input works well for this, and Svelte’s binding makes it easy to work with.
What You’ll Learn
- Bind to date input values
- Set minimum and maximum dates
- Format dates for display
- Handle date validation
The Basic Date Input
Date inputs bind just like text inputs:
<script>
let bookingDate = $state('');
</script>
<label for="booking-date">Preferred Date</label>
<input
type="date"
id="booking-date"
bind:value={bookingDate}
/>
<p>Selected: {bookingDate || 'No date selected'}</p> The value is a string in YYYY-MM-DD format (e.g., “2025-06-15”).
Prevent Past Dates
Customers can’t book services for yesterday. Set a minimum date:
<script>
let bookingDate = $state('');
// Get today's date in YYYY-MM-DD format
function getTodayString() {
return new Date().toISOString().split('T')[0];
}
let minDate = getTodayString();
</script>
<label for="booking-date">Preferred Date</label>
<input
type="date"
id="booking-date"
bind:value={bookingDate}
min={minDate}
required
/> The browser now greys out past dates in the picker.
Limit How Far Ahead
Maybe you only book 3 months in advance:
<script>
let bookingDate = $state('');
function getDateString(date) {
return date.toISOString().split('T')[0];
}
let today = new Date();
let minDate = getDateString(today);
// 3 months from now
let maxDate = getDateString(
new Date(today.getFullYear(), today.getMonth() + 3, today.getDate())
);
</script>
<label for="booking-date">Preferred Date</label>
<input
type="date"
id="booking-date"
bind:value={bookingDate}
min={minDate}
max={maxDate}
required
/>
<p class="hint">Book up to 3 months in advance</p> Format for Display
The raw YYYY-MM-DD format isn’t user-friendly. Format it nicely:
<script>
let bookingDate = $state('');
function formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString + 'T00:00:00');
return date.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
let formattedDate = $derived(formatDate(bookingDate));
</script>
<label for="booking-date">Preferred Date</label>
<input
type="date"
id="booking-date"
bind:value={bookingDate}
required
/>
{#if bookingDate}
<p class="selected-date">{formattedDate}</p>
{/if} Now “2025-06-15” displays as “Sunday, June 15, 2025”.
Note: We add T00:00:00 to avoid timezone issues when parsing the date string.
Add to the Booking Form
Integrate the date picker with the contact fields:
<!-- filename: src/lib/components/BookingForm.svelte -->
<script>
// Contact fields
let customerName = $state('');
let customerEmail = $state('');
// Date selection
let bookingDate = $state('');
function getDateString(date) {
return date.toISOString().split('T')[0];
}
let today = new Date();
let minDate = getDateString(today);
let maxDate = getDateString(
new Date(today.getFullYear(), today.getMonth() + 3, today.getDate())
);
function formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString + 'T00:00:00');
return date.toLocaleDateString('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric'
});
}
</script>
<form>
<fieldset>
<legend>Contact Information</legend>
<!-- Name and email fields... -->
</fieldset>
<fieldset>
<legend>Appointment Details</legend>
<div class="field">
<label for="booking-date">Preferred Date</label>
<input
type="date"
id="booking-date"
name="bookingDate"
bind:value={bookingDate}
min={minDate}
max={maxDate}
required
/>
{#if bookingDate}
<p class="date-preview">{formatDate(bookingDate)}</p>
{/if}
</div>
</fieldset>
</form>
<style>
.date-preview {
margin: 0.25rem 0 0 0;
color: #007bff;
font-size: 0.875rem;
}
</style> Check Day of Week
Maybe you don’t work weekends:
<script>
let bookingDate = $state('');
let isWeekend = $derived(() => {
if (!bookingDate) return false;
const date = new Date(bookingDate + 'T00:00:00');
const day = date.getDay();
return day === 0 || day === 6; // Sunday or Saturday
});
</script>
<input type="date" bind:value={bookingDate} />
{#if isWeekend()}
<p class="warning">
⚠️ We don't offer services on weekends. Please select a weekday.
</p>
{/if} This provides immediate feedback, though server-side validation will ultimately enforce the rule.
Default to Tomorrow
Pre-select a sensible default:
<script>
function getDateString(date) {
return date.toISOString().split('T')[0];
}
function getTomorrow() {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
return getDateString(tomorrow);
}
let bookingDate = $state(getTomorrow());
</script> The form starts with tomorrow selected, saving customers a click.
Common Mistakes
Timezone Parsing Issues
<script>
let dateString = '2025-06-15';
// ❌ May give wrong day due to timezone
const date = new Date(dateString);
// ✅ Explicit time prevents timezone shift
const date = new Date(dateString + 'T00:00:00');
</script> Forgetting min Attribute
<!-- ❌ Users can select past dates -->
<input type="date" bind:value={bookingDate} />
<!-- ✅ Prevent past dates -->
<input type="date" bind:value={bookingDate} min={today} /> Always set min to prevent invalid selections.
Summary
Date inputs work seamlessly with Svelte’s binding. Use min and max to constrain valid ranges, and format dates nicely for display. The native date picker handles most complexity.
Key takeaways:
bind:valueworks withtype="date"- Values are strings in
YYYY-MM-DDformat - Use
minandmaxto constrain date ranges - Format with
toLocaleDateString()for display
Next Steps
Customers pick a date, but what time? Continue with Time Selection Dropdown to add time slot selection.