Skip to content
IzzyBlazor 0.1.0-alpha.20

Enter all results ↑ ↓ move Esc close

TimeField

Since 0.1.0-alpha.20
A time of day, in the browser's own input, with a list of times to choose from.

Static server-side rendering: no circuit, no WebAssembly.

A time of day.

Usage

razor
<TimeField @bind-Value="Model.Opens" />
<TimeField @bind-Value="Model.Opens" Min="@nine" Max="@five" Step="TimeSpan.FromMinutes(15)" />
<TimeField @bind-Value="Model.Shift" Min="@ten" Max="@six" /> a window across midnight
<TimeField @bind-Value="Model.Opens" TimeDisabled="t => t.Hour == 12" />
<TimeField @bind-Value="Model.Opens" UseNative />

Limits

Min and Max come from [Range], or set them on the field, as Closes's Min follows Opens. Set Min after Max for a window across midnight, as Night shift does.

Preview

Doors open in the morning.

Between 10 PM and 6 AM.

Code

Limits.razor
@using System.ComponentModel.DataAnnotations

<Form Model="Model" FormName="time-field-limits" OnValidSubmit="Save" MaxWidth="20.Rem" Grow>
    <TimeField @bind-Value="Model!.Opens" Hint="Doors open in the morning." />
    <TimeField @bind-Value="Model!.Closes" Min="Model!.Opens" />
    <TimeField @bind-Value="Model!.Night" Label="Night shift starts" Min="new TimeOnly(22, 0)" Max="new TimeOnly(6, 0)" Hint="Between 10 PM and 6 AM." />
    <Row><Button Submit>Save hours</Button></Row>
    @if (_saved is { } saved)
    {
        <Alert Status="Status.Success">Saved: open @saved.Opens.ToString("HH:mm") to @(saved.Closes?.ToString("HH:mm") ?? "late"), night shift from @(saved.Night?.ToString("HH:mm") ?? "no one").</Alert>
    }
</Form>

@code {
    [SupplyParameterFromForm(FormName = "time-field-limits")]
    private Hours? Model { get; set; }

    // What was saved, not the fields: on an interactive page they follow typing.
    private (TimeOnly Opens, TimeOnly? Closes, TimeOnly? Night)? _saved;

    protected override void OnInitialized() => Model ??= new();

    private void Save() => _saved = (Model!.Opens!.Value, Model.Closes, Model.Night);

    public sealed class Hours
    {
        [Required, Range(typeof(TimeOnly), "06:00", "12:00", ErrorMessage = "Pick a time between 6 AM and noon.")]
        public TimeOnly? Opens { get; set; } = new TimeOnly(9, 0);

        public TimeOnly? Closes { get; set; }

        public TimeOnly? Night { get; set; }
    }
}

Static: The server turns away a time outside the limits, whatever the browser let through.

The list of times

The list has a time every Step, or every 30 minutes with none, in which case the input still takes any minute. TimeDisabled turns times off, and holds on the server too. UseNative keeps the browser's picker.

Preview

Every 15 minutes, 9 to 5, with no visits over lunch.

Code

Slots.razor
<Form Model="Model" FormName="time-field-slots" OnValidSubmit="Save" MaxWidth="20.Rem" Grow>
    <TimeField @bind-Value="Model!.Visit" Min="new TimeOnly(9, 0)" Max="new TimeOnly(17, 0)" Step="TimeSpan.FromMinutes(15)" TimeDisabled="AtLunch" Clearable Hint="Every 15 minutes, 9 to 5, with no visits over lunch." />
    <Row><Button Submit>Book the visit</Button></Row>
    @if (_saved is { } saved)
    {
        <Alert Status="Status.Success">Booked for @saved.ToString("HH:mm").</Alert>
    }
</Form>

@code {
    [SupplyParameterFromForm(FormName = "time-field-slots")]
    private Booking? Model { get; set; }

    // What was saved, not the field: on an interactive page it follows typing.
    private TimeOnly? _saved;

    protected override void OnInitialized() => Model ??= new();

    private static bool AtLunch(TimeOnly time) => time.Hour == 12;

    private void Save() => _saved = Model!.Visit;

    public sealed class Booking
    {
        public TimeOnly? Visit { get; set; } = new TimeOnly(10, 30);
    }
}

Steps, sizes, read-only and disabled

Use Step for the allowed increments; one under a minute shows seconds.

Preview

Read-only: posted, but can't be changed.

Disabled: not posted.

Code

States.razor
<Form Model="Model" FormName="time-field-states" MaxWidth="20.Rem" Grow>
    <TimeField @bind-Value="Model!.Quarter" Label="Quarter hours" Step="TimeSpan.FromMinutes(15)" />
    <TimeField @bind-Value="Model!.Seconds" Label="With seconds" Step="TimeSpan.FromSeconds(1)" />
    <TimeField @bind-Value="Model!.Small" Label="Small" Size="ControlSize.Sm" />
    <TimeField @bind-Value="Model!.Large" Label="Large" Size="ControlSize.Lg" />
    <TimeField @bind-Value="Model!.Signed" Label="Signed at" ReadOnly Hint="Read-only: posted, but can't be changed." />
    <TimeField @bind-Value="Model!.Renews" Label="Renews at" Disabled Hint="Disabled: not posted." />
</Form>

@code {
    [SupplyParameterFromForm(FormName = "time-field-states")]
    private Contract? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    public sealed class Contract
    {
        public TimeOnly Quarter { get; set; } = new(9, 15);
        public TimeOnly Seconds { get; set; } = new(9, 15, 30);
        public TimeOnly Small { get; set; } = new(9, 0);
        public TimeOnly Large { get; set; } = new(9, 0);
        public TimeOnly Signed { get; set; } = new(16, 30);
        public TimeOnly Renews { get; set; } = new(0, 0);
    }
}

Details

A time has no date or zone, so nothing converts it. The input shows 12 or 24 hours as the browser does, which the page can't set; the list follows the page's culture.

The list has a time every Step, or every 30 minutes with no Step, in which case the input still takes any minute. With a Step of seconds, or one so short the list would pass 288 times, there's a box for each part of the time and OK instead, and nothing is written until OK. UseNative keeps the browser's picker. So do no script and a phone, unless the field has TimeDisabled, which a browser's picker can't show: there it's the library's, and on a phone the input can't be typed in. Min, Max and TimeDisabled are checked again on the server, and the boxes leave them to that and the browser.

Mode support

What works in each mode, TimeField
FeatureStaticInteractive
The browser's input, with Min, Max and Step checked before posting, and Min, Max and disabled times checked again on the serverYesYes
A list of times from Step, within Min and MaxYesYes
Binds TimeOnly, and a window across midnight when Min is after MaxYesYes

Static: static server-side rendering, with no circuit and no WebAssembly. Interactive: Server, WebAssembly or Auto.

Without JavaScript

Every page starts as plain HTML: before IzzyBlazor's script loads on a static page, while an interactive page prerenders, and with JavaScript off. With JavaScript off, the browser's own picker opens in place of the library's list.

Accessibility

  • It renders the browser's own time input with a label linked to it: screen readers read each part (hour, minute) and arrow keys change it.
  • Label, hint and errors work as in TextField.
  • The list's button is named "Choose time" (ChooseLabel), or "Change time" and the time once there is one. Its panel is a non-modal dialog, named by the button, holding a listbox, with the chosen time selected, or a labelled group of boxes. Focus goes to the chosen time, or the next from now, or the first box, and on closing back to where it opened from.

Keyboard navigation

In the time field

TimeField keys, In the time field
Press this keyTo do this
Up or DownChange the focused part of the time
Left or RightMove between the parts of the time
Alt+DownOpen the list

In the list

TimeField keys, In the list
Press this keyTo do this
Up or DownMove a time
Home or EndGo to the first or last time
Enter or SpaceChoose the time and close
Tab or Shift+TabClose, and go on from its button
EscapeClose without changing the value

In the boxes

TimeField keys, In the boxes
Press this keyTo do this
Up or DownChange the hour, minute or second
EnterSave the time, and close
Tab or Shift+TabMove through the boxes and OK, and close past either end
EscapeClose without changing the value

Parameters

TimeField parameters
PropTypeDefault
ReadOnlyMakes the field read-only: it can be focused, and it still posts.boolfalse
MinThe earliest time.TimeOnly?computed
MaxThe latest time.TimeOnly?computed
StepThe step between allowed times, counted from Min, or from midnight with no Min.TimeSpan?
TimeDisabledWhether a time can't be chosen.Func<TimeOnly, bool>?
ClearableA button in the field that empties it, for a nullable value, there while it holds something.boolfalse
UseNativeKeeps the browser's picker in place of the library's list.boolfalse
ChooseLabelThe name of the list's button, in place of "Choose time" and "Change time" with the time.string?
StartAddonContent attached before the control, outside its border.RenderFragment?
EndAddonContent attached after the control, outside its border.RenderFragment?
@bind-ValueThe value, bound with @bind-Value.TValue
DisplayNameThe field's name in validation messages from the input itself, such as a value that can't be parsed.string?

See also

  • DateField: a date to type or choose from a calendar, or a date and time.
  • TextField: a labeled text input with add-ons and a password reveal.
  • Form: posts on static pages, validates live on interactive ones.

Connection lost

Rejoining the server…