Manual · Getting started · Code examples · Models
When to use it
Select a calendar date or local wall-clock time without automatic timezone conversion.
Appearance and live example
Try the Blazor example · Flutter example code
The live Blazor preview is embedded above. Use Reset to restore its initial state. Flutter implementation code is provided below; run the Flutter gallery from the installed developer workspace. Dialogs and drawers start closed; use their Open button. Tooltips appear on hover or keyboard focus.
Behavior and practical rules
Input format: yyyy-MM-dd. Min/Max include boundary values. Invalid dates such as April 31 and times such as 24:00 are rejected. DisabledDate returns true for unavailable days. Blazor uses DateOnly, TimeOnly or DateTime; Flutter uses DateTime or TimeOfDay. Normalize timezones at application boundaries. Empty optional input is null. Validate required values through the form; Flutter also exposes required. See forms and dates for supported calendar interactions and parsing limitations.
ReadOnly/readOnly prevents user changes. Disabled/enabled also disables interaction. Date editors keep readable, focusable text in read-only mode and disable their picker action; Calendar blocks selection and navigation (Flutter also excludes keyboard focus). Bounds must be ordered; invalid configuration throws. Values are Gregorian calendar dates; date text is ISO yyyy-MM-dd, independent of Blazor's current culture. Empty optional input clears to null.
DisabledDate/disabledDate applies to typing and calendar selection. In a range it checks both endpoints, not every date between them. Partial and reversed ranges fail form validation. Flutter range validation reads the current parent value after replacement. Applications own validation of external single-date values. Replace the form key to discard an invalid draft when the model value is unchanged.
Flutter calendars use Material locale/week-start and default bounds 1900–2100; Blazor uses Culture/FirstDayOfWeek and DateOnly bounds. Supply explicit bounds for matching domains. Calendar selection is single-date only. Shared range highlighting, multiple calendar views, cell templates, week numbers, segmented/custom-format input and complete keyboard/screen-reader parity remain open. Flutter popup results are ignored after a parent rebuild, edit or disposal.
Blazor example
<NgDateInput @bind-Value="value" Min="min" Max="max" DisabledDate="Unavailable" ReadOnly="readOnly" />
<NgButton OnClick="Toggle">Read only</NgButton>
<p>Accepted date: @value</p>
@code {
private DateOnly? value=new(2026,10,20); private bool readOnly;
private DateOnly min=new(2026,10,1), max=new(2026,10,31);
private bool Unavailable(DateOnly d)=>d.DayOfWeek==DayOfWeek.Sunday;
private void Toggle()=>readOnly=!readOnly;
}Flutter example
DateTime? value=DateTime(2026,10,20); bool readOnly=false;
Widget build(BuildContext context)=>Column(crossAxisAlignment:CrossAxisAlignment.start, children:[
NgDateInput(value:value,min:DateTime(2026,10,1),max:DateTime(2026,10,31),
readOnly:readOnly,disabledDate:(d)=>d.weekday==DateTime.sunday,
onChanged:(v)=>setState(()=>value=v)),
NgButton(onPressed:()=>setState(()=>readOnly=!readOnly),child:const Text('Read only')),
Text('Accepted date: $value'),
]);Blazor parameters and events
Names are case-sensitive. ? permits null. EditorRequired parameters are marked required; other values use the initializer or CLR default.
| Parameter | Type | Default / requirement | Purpose |
|---|---|---|---|
Id |
string |
"ng-"+Guid.NewGuid().ToString("N") | See the behavior rules and model contract above. |
Label |
string |
"Date" | Visible label or accessible name. |
Min |
DateOnly? |
not set | Inclusive minimum. |
Max |
DateOnly? |
not set | Inclusive maximum. |
DisabledDate |
Func<DateOnly,bool>? |
not set | See the behavior rules and model contract above. |
Disabled |
bool |
false | Disable user interaction. |
ReadOnly |
bool |
false | Prevent changes while retaining supported viewing actions. |
Value |
DateOnly? |
model value | Current field value. |
ValueChanged |
EventCallback<DateOnly?> |
not set | Value change callback. |
ValueExpression |
Expression<Func<DateOnly?>> |
required | Supplied by @bind-Value; pass explicitly with manual binding. |
AdditionalAttributes |
HTML attribute dictionary | null | Extra HTML/ARIA attributes. |
Flutter parameters and events
required marks a mandatory argument even if its type is nullable. key is the standard Flutter Key. The exact constructor below specifies defaults.
| Argument | Type | Purpose |
|---|---|---|
label |
String |
Visible label or accessible name. |
value |
DateTime? |
Current value; see state ownership and model rules above. |
min |
DateTime? |
Inclusive minimum. |
max |
DateTime? |
Inclusive maximum. |
required |
bool |
Require a nonempty/selected value during form validation. |
enabled |
bool |
See the behavior rules and model contract above. |
readOnly |
bool |
Prevent changes while retaining supported viewing actions. |
disabledDate |
bool Function(DateTime)? |
See the behavior rules and model contract above. |
onChanged |
ValueChanged<DateTime?>? |
Store the new value using setState or your state manager. |
const NgDateInput({
super.key,
this.label = 'Date',
required this.value,
this.onChanged,
this.min,
this.max,
this.required = false,
this.enabled = true,
this.readOnly = false,
this.disabledDate,
});Integration and troubleshooting
If the UI does not update, confirm that the parent stores callback values and passes them back. Blazor event handlers need interactive rendering; Flutter requires setState or a state manager. Submit form data only after successful validation.
Check accessible labels, empty/invalid states, disabled actions and narrow layouts. Keyboard support is not full screen-reader certification. Current visual verification targets Web in visible Chrome on Linux/iMac; native mobile platforms are a separate phase.
Source and complete examples
- Blazor source
- Flutter source
- Galleries and launch commands
- Capability matrix
API declarations are generated from current source. Curated examples and behavior live in scripts/manual_content.py; regenerate with python3 scripts/generate_manual.py.