Adding a Date/Time Picker to Your App
A focused guide to BptDateSelector, BptTimeSelector, BptDateTimeSelector, and BptDateRangeSelector. Covers format strings, range constraints, and culture.
BptDateSelector— date only (yyyy-MM-dd).BptTimeSelector— time only (HH:mm), 12- or 24-hour.BptDateTimeSelector— combined date + time in a single control.BptDateRangeSelector— two coupled date pickers for "from – to" ranges.
Step 1: A basic date picker
The minimum useful markup is a single bound field. Value is DateTime?,
so null means "nothing selected yet".
<BptDateSelector @bind-Value="_birthday" />
@code {
private DateTime? _birthday;
}
The picker pops a calendar on click, lets the user navigate by month/year, and writes the selected
value back through the standard ValueChanged callback.
Step 2: Constrain the range
Pass Min and Max as DateTime? to grey out invalid days.
The component enforces the constraint visually and programmatically — it won't accept a
keyboard entry outside the range.
<!-- Birthday: must be in the past, at most 120 years ago -->
<BptDateSelector @bind-Value="_birthday"
Min="DateTime.Today.AddYears(-120)"
Max="DateTime.Today" />
<!-- Booking: only future dates -->
<BptDateSelector @bind-Value="_checkInDate"
Min="DateTime.Today"
Placeholder="Check-in date" />Step 3: Format the displayed value
The Format parameter takes any standard or custom DateTime format string.
It controls how the chosen date renders in the input — the underlying bound value is
always a real DateTime, so consumers of the model don't need to parse anything.
| Format | Example output | When to use |
|---|---|---|
yyyy-MM-dd (default) | 2026-05-16 | ISO 8601 — language-neutral, sortable, ideal for technical UIs and logs. |
dd/MM/yyyy | 16/05/2026 | European day-first format. Friendly for general consumer apps in the EU. |
MM/dd/yyyy | 05/16/2026 | US month-first format. |
d MMM yyyy | 16 May 2026 | Localized month abbreviation. Avoids ambiguity between dd/MM and MM/dd. |
dddd, d MMMM yyyy | Saturday, 16 May 2026 | Long form — good for confirmation screens. |
Format controls the structure; the active CultureInfo controls the
language. dddd, d MMMM yyyy under nb-NO renders as
"lørdag, 16 mai 2026". Use BptLanguage in your layout to let users switch culture at runtime.
Step 4: Time pickers
BptTimeSelector binds to a TimeSpan? rather than DateTime?.
Use HourStep and MinuteStep to constrain selectable increments — common
for booking systems where slots are every 15 or 30 minutes.
<BptTimeSelector @bind-Value="_meetingStart"
Format="HH:mm"
MinuteStep="15"
Use24HourFormat="true" />
@code {
private TimeSpan? _meetingStart = new TimeSpan(9, 0, 0); // 09:00 default
}
Switch to Use24HourFormat="false" and the picker shows an AM/PM toggle. Pair it with
a 12-hour format string like h:mm tt for the conventional US rendering.
Step 5: Combined date + time
For appointment scheduling, log entries, or anything that needs a single moment in time,
BptDateTimeSelector avoids the awkward "two controls glued together" feel.
<BptDateTimeSelector @bind-Value="_appointment"
Format="yyyy-MM-dd HH:mm"
MinDate="DateTime.Today"
MaxDate="DateTime.Today.AddMonths(3)"
MinHour="8"
MaxHour="18"
Placeholder="Pick an appointment slot" />
@code {
private DateTime? _appointment;
}
Note the parameter names differ from BptDateSelector: it's MinDate /
MaxDate rather than Min / Max, because there are
also MinHour / MaxHour parameters that constrain the time part.
This lets you express "any weekday between 8 AM and 6 PM in the next quarter" with a single control.
Step 6: Date ranges
BptDateRangeSelector renders two coupled date pickers — picking a start date enforces
the end date to be after it, and vice versa.
<BptDateRangeSelector @bind-StartDate="_from"
@bind-EndDate="_to"
StartPlaceholder="Check-in"
EndPlaceholder="Check-out" />
@code {
private DateTime? _from;
private DateTime? _to;
}
Two-way binding here uses the field-specific form (@bind-StartDate,
@bind-EndDate) because there's no single Value — the control exposes
a pair. The OnRangeSelected callback (parameterless) fires once both ends are chosen,
which is the right hook for "search hotels" or "filter results" actions.
Parameter quick-reference
| Parameter | Date | Time | DateTime | Range |
|---|---|---|---|---|
Value (bind) | DateTime? | TimeSpan? | DateTime? | — (use StartDate/EndDate) |
Min / Max | ✓ | ✓ (TimeSpan?) | — | — |
MinDate / MaxDate | — | — | ✓ | ✓ |
MinHour / MaxHour | — | — | ✓ | — |
Format | "yyyy-MM-dd" | "HH:mm" | "yyyy-MM-dd HH:mm" | per-end |
HourStep / MinuteStep | — | ✓ | — | — |
Use24HourFormat | — | ✓ | — | — |
Placeholder | ✓ | ✓ | ✓ | Start/EndPlaceholder |
Disabled | ✓ | ✓ | ✓ | ✓ |
Common gotchas
- DateTimeKind matters. Both date and date-time selectors emit
DateTimeKind.Unspecifiedvalues — they describe a "wall-clock" moment, not a UTC instant. If you store them in a database, decide explicitly whether to interpret them as local or UTC and convert before persisting. - Min/Max are inclusive.
Max="DateTime.Today"lets the user pick today's date. UseDateTime.Today.AddDays(-1)if you want a strict "must be in the past" rule. - TimeSpan can exceed 24h.
BptTimeSelector'sValueis aTimeSpan?, which has no built-in cap at 24 hours. The control's UI clamps the display, but if you setValueprogrammatically toTimeSpan.FromHours(30)you'll see "06:00". Always normalize inputs.