Skip to content
IzzyBlazor 0.1.0-alpha.20

Enter all results ↑ ↓ move Esc close

MultiDateField

Since 0.1.0-alpha.20
Several separate days to choose from a month.

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

Several separate days, chosen from a month. Bind it to a collection of DateOnly: an array, List<T>, HashSet<T> or an interface they implement. The dates come back in order, each once.

Usage

razor
<MultiDateField @bind-Value="Model.DaysOff" />
<MultiDateField @bind-Value="Model.DaysOff" Min="@today" DateDisabled="d => d.DayOfWeek == DayOfWeek.Sunday" />
<MultiDateField @bind-Value="Model.DaysOff" Inline />

Days off

A day toggles and writes at once, so the panel stays open. Required needs at least one, and the rules hold for each date on the server.

Preview

Weekends are off already.

Code

DaysOff.razor
<Form Model="Model" FormName="multi-date-field-days-off" OnValidSubmit="Save" MaxWidth="20.Rem" Grow>
    <MultiDateField @bind-Value="Model!.DaysOff" Label="Days off" Min="@First" DateDisabled="IsWeekend" Clearable Required
                    Hint="Weekends are off already." />
    <Row><Button Submit>Save</Button></Row>
    @if (_saved is { } saved)
    {
        <Alert Status="Status.Success">Days off saved: @saved.</Alert>
    }
</Form>

@code {
    private static readonly DateOnly First = new(2027, 3, 1);

    [SupplyParameterFromForm(FormName = "multi-date-field-days-off")]
    private Request? Model { get; set; }

    private int? _saved;

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

    private void Save() => _saved = Model!.DaysOff?.Count;

    private static bool IsWeekend(DateOnly day) => day.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;

    public sealed class Request
    {
        public List<DateOnly>? DaysOff { get; set; } = [new(2027, 3, 1), new(2027, 3, 5)];
    }
}

On the page

Use Inline for the month on the page, in place of the button.

Preview

March 2027
SunMonTueWedThuFriSat

Code

Inline.razor
<Form Model="Model" FormName="multi-date-field-inline" OnValidSubmit="Save" Grow>
    <MultiDateField @bind-Value="Model!.Sessions" Inline />
    <Row><Button Submit>Save</Button></Row>
    @if (_saved is { } saved)
    {
        <Alert Status="Status.Success">Sessions saved: @saved.</Alert>
    }
</Form>

@code {
    [SupplyParameterFromForm(FormName = "multi-date-field-inline")]
    private Plan? Model { get; set; }

    private int? _saved;

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

    private void Save() => _saved = Model!.Sessions?.Length;

    public sealed class Plan
    {
        public DateOnly[]? Sessions { get; set; } = [new(2027, 3, 9), new(2027, 3, 16)];
    }
}

Details

A day toggles and writes at once, so the panel stays open with nothing to confirm. Inline shows the month on the page in place of the button. Min, Max and DateDisabled are checked for each date on the server, so they hold against a crafted post. With Required, or [Required], it needs at least one. For a run of days in a row, use DateRangeField.

Mode support

What works in each mode, MultiDateField
FeatureStaticInteractive
A month where each day toggles, in a panel or on the pageYesYes
Min, Max and DateDisabled checked for each date on the serverYesYes
Binds an array, List or HashSet of DateOnlyYesYes

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, it's a date input for each chosen date and one empty one, so one more can be added each time the form posts.

Accessibility

  • The button stands in for an input, so it's named by the field's label and the dates, and takes the hint and errors. Its panel is a non-modal dialog, named by the button.
  • The month is a grid with aria-multiselectable, and each chosen day has aria-selected. A polite announcement says what each press added or removed.
  • With JavaScript off, it's a labelled date input for each date, and one empty.

Keyboard navigation

On the button

MultiDateField keys, On the button
Press this keyTo do this
Enter or SpaceOpen the month

In the days

MultiDateField keys, In the days
Press this keyTo do this
Left or RightMove a day (reversed in right-to-left)
Up or DownMove a week
Home or EndGo to the start or end of the week
Page Up or Page DownMove a month, keeping the day number or the month's last day
Shift+Page Up or Shift+Page DownMove a year
Enter or SpaceAdd the date, or take it off

In the panel

MultiDateField keys, In the panel
Press this keyTo do this
Tab or Shift+TabMove through the header and the days, and close past either end
EscapeClose, keeping the dates

Parameters

MultiDateField parameters
PropTypeDefault
ReadOnlyMakes the field read-only: the dates show in a read-only text field, and still post.boolfalse
MinThe earliest day that can be chosen, checked for each date on the server.DateOnly?
MaxThe latest day that can be chosen, checked for each date on the server.DateOnly?
InlineShows the month on the page in place of a button that opens it.boolfalse
ClearableA button in the field that takes off every date, there while there are any.boolfalse
ChooseLabelThe name of the button, in place of "Choose dates" and "Change dates" with the dates.string?
FirstDayOfWeekThe first column.DayOfWeek?computed
CultureThe culture for the month and day names, the first day and the week numbers.CultureInfo?computed
ShowWeekNumbersAdds a first column with the week of the year, counted as the culture counts them.boolfalse
ShowAdjacentDaysWhether to show the days of the months before and after, muted, in the first and last weeks.booltrue
DateDisabledWhether a day can't be chosen.Func<DateOnly, bool>?
DateDisabledWindowHow far each way from the value or today to call DateDisabled and DayClass, in whole days, for an end the limits don't set.TimeSpan?
DayClassA class for a day's button, or null.Func<DateOnly, string?>?
@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.
  • DateRangeField: two whole days, both included, in the browser's own date inputs.
  • Calendar: a month on the page, with the browser's own date input posting the day.
  • MultiSelect: several choices as chips you can type to filter.

Connection lost

Rejoining the server…