Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ExampleCard ComponentName="DateTimePicker" ExampleName="DateTimePickerExample1" Title="Usage" Description="MudDateTimePicker handles date and time selection itself.">
<DateTimePickerExample1 />
</ExampleCard>
<ExampleCard ComponentName="DateTimePicker" ExampleName="DateTimePickerExample2" Title="Generic Types" Description="MudDateTimePicker supports DateTime and DateTimeOffset.">
<ExampleCard ComponentName="DateTimePicker" ExampleName="DateTimePickerExample2" Title="Generic Types" Description="MudDateTimePicker supports DateTime, DateTimeOffset and DateOnly.">
<DateTimePickerExample2 />
</ExampleCard>
<ExampleCard ComponentName="DateTimePicker" ExampleName="DateTimePickerExample3" Title="Action Buttons" Description="Submit strategy can be handled via Action Buttons and AutoClose parameter.">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@

<MudGrid>
<MudItem xs="12" sm="8">
<MudDateTimePicker @bind-Value="_date" Editable="_editable" Label="DateTime" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_date2" Editable="_editable" Label="DateTimeOffset" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_date2" Editable="_editable" Label="TimeZone Istanbul" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary"
TimeZone="@TimeZoneInfo.FindSystemTimeZoneById("Europe/Istanbul")" />
<MudDateTimePicker @bind-Value="_date3" Editable="_editable" Label="DateOnly" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudStack Spacing="2">
<MudDateTimePicker @bind-Value="_dateTime" Editable="_editable" Label="DateTime" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_nullableDateTime" Editable="_editable" Label="DateTime?" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_dateTimeOffset" Editable="_editable" Label="DateTimeOffset" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_nullableDateTimeOffset" Editable="_editable" Label="DateTimeOffset?" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_dateTimeOffset" Editable="_editable" Label="TimeZone Istanbul" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary"
TimeZone="@TimeZoneInfo.FindSystemTimeZoneById("Europe/Istanbul")" />
<MudDateTimePicker @bind-Value="_dateOnly" Editable="_editable" Label="DateOnly" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
<MudDateTimePicker @bind-Value="_nullableDateOnly" Editable="_editable" Label="DateOnly?" Clearable="_clearable" Variant="Variant.Outlined" Color="Color.Primary" />
</MudStack>
</MudItem>

<MudItem xs="12" sm="4">
Expand All @@ -19,9 +24,14 @@
</MudGrid>

@code {
private DateTime? _date = DateTime.Now;
private DateTimeOffset _date2 = DateTimeOffset.UtcNow;
private DateOnly _date3 = DateOnly.FromDateTime(DateTime.Now);
private DateTime _dateTime = DateTime.Now;
private DateTime? _nullableDateTime;
private DateTimeOffset _dateTimeOffset = DateTimeOffset.UtcNow;
private DateTimeOffset? _nullableDateTimeOffset;
private DateOnly _dateOnly = DateOnly.FromDateTime(DateTime.Now);
private DateOnly? _nullableDateOnly;
private bool _clearable = false;
private bool _editable = false;
}


Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,61 @@

<MudGrid>
<MudItem xs="12" sm="8">
<MudDateTimePicker @ref="_picker" @bind-Value="_date" Editable="_editable" Label="Date" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _picker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _picker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _picker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>
<MudStack Spacing="2">
<MudDateTimePicker @ref="_dateTimePicker" @bind-Value="_dateTime" Editable="_editable" Label="DateTime" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _dateTimePicker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _dateTimePicker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _dateTimePicker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>

<MudDateTimePicker @ref="_nullableDateTimePicker" @bind-Value="_nullableDateTime" Editable="_editable" Label="DateTime?" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _nullableDateTimePicker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _nullableDateTimePicker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _nullableDateTimePicker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>

<MudDateTimePicker @ref="_dateTimeOffsetPicker" @bind-Value="_dateTimeOffset" Editable="_editable" Label="DateTimeOffset" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _dateTimeOffsetPicker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _dateTimeOffsetPicker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _dateTimeOffsetPicker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>

<MudDateTimePicker @ref="_nullableDateTimeOffsetPicker" @bind-Value="_nullableDateTimeOffset" Editable="_editable" Label="DateTimeOffset?" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _nullableDateTimeOffsetPicker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _nullableDateTimeOffsetPicker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _nullableDateTimeOffsetPicker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>

<MudDateTimePicker @ref="_dateOnlyPicker" @bind-Value="_dateOnly" Editable="_editable" Label="DateOnly" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _dateOnlyPicker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _dateOnlyPicker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _dateOnlyPicker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>

<MudDateTimePicker @ref="_nullableDateOnlyPicker" @bind-Value="_nullableDateOnly" Editable="_editable" Label="DateOnly?" Clearable="_clearable"
ShowToolbar="_showToolbar" Variant="_variant" Color="_color" DateFormat="@_dateFormat">
<PickerActions>
<MudButton Class="mr-auto align-self-start" OnClick="@(() => _nullableDateOnlyPicker.ClearAsync())">Clear</MudButton>
<MudButton OnClick="@(() => _nullableDateOnlyPicker.CloseAsync(false))">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="@(() => _nullableDateOnlyPicker.CloseAsync())">OK</MudButton>
</PickerActions>
</MudDateTimePicker>
</MudStack>
</MudItem>

<MudItem xs="12" sm="4">
Expand All @@ -32,15 +79,25 @@
}
</MudSelect>
<MudTextField @bind-Value="_dateFormat" Variant="Variant.Outlined" Label="Date Format" />
<MudButton OnClick="@(() => _date = DateTime.Now)">Set Today</MudButton>
<MudButton OnClick="SetCurrentValues">Set Current Values</MudButton>
</MudStack>
</MudItem>
</MudGrid>

@code {
private MudDateTimePicker<DateTime?> _picker = null!;
private MudDateTimePicker<DateTime> _dateTimePicker = null!;
private MudDateTimePicker<DateTime?> _nullableDateTimePicker = null!;
private MudDateTimePicker<DateTimeOffset> _dateTimeOffsetPicker = null!;
private MudDateTimePicker<DateTimeOffset?> _nullableDateTimeOffsetPicker = null!;
private MudDateTimePicker<DateOnly> _dateOnlyPicker = null!;
private MudDateTimePicker<DateOnly?> _nullableDateOnlyPicker = null!;

private DateTime? _date = DateTime.Now;
private DateTime _dateTime = DateTime.Now;
private DateTime? _nullableDateTime;
private DateTimeOffset _dateTimeOffset = DateTimeOffset.UtcNow;
private DateTimeOffset? _nullableDateTimeOffset;
private DateOnly _dateOnly = DateOnly.FromDateTime(DateTime.Now);
private DateOnly? _nullableDateOnly;
private bool _editable = false;
private bool _showToolbar = true;
private bool _submitOnClose = true;
Expand All @@ -49,4 +106,16 @@
private bool _isAdornmentEnd = true;
private bool _clearable = false;
private Variant _variant = Variant.Outlined;

private void SetCurrentValues()
{
_dateTime = DateTime.Now;
_nullableDateTime = DateTime.Now;
_dateTimeOffset = DateTimeOffset.UtcNow;
_nullableDateTimeOffset = DateTimeOffset.UtcNow;
_dateOnly = DateOnly.FromDateTime(DateTime.Now);
_nullableDateOnly = DateOnly.FromDateTime(DateTime.Now);
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ protected MudBaseDatePickerX()
/// The current month shown in the date picker.
/// </summary>
/// <remarks>
/// Defaults to the current month.<br />
/// Defaults to the current month.
/// When bound via <c>@bind-PickerMonth</c>, controls the initial month displayed. This value is always the first day of a month.
/// </remarks>
[Parameter]
Expand All @@ -133,7 +133,7 @@ public DateTime? PickerMonth
/// The delay, in milliseconds, before closing the picker after a value is selected.
/// </summary>
/// <remarks>
/// Defaults to <c>100</c>.<br />
/// Defaults to <c>100</c>.
/// This delay helps the user see that a date has been selected before the popover disappears.
/// </remarks>
[Parameter] public int ClosingDelay { get; set; } = 100;
Expand All @@ -150,7 +150,7 @@ public DateTime? PickerMonth
/// The maximum number of months allowed in one row.
/// </summary>
/// <remarks>
/// Defaults to <c>null</c>.<br />
/// Defaults to <c>null</c>.
/// When <c>null</c>, the <see cref="DisplayMonths"/> is used.
/// </remarks>
[Parameter] public int? MaxMonthColumns { get; set; }
Expand All @@ -172,7 +172,7 @@ public DateTime? PickerMonth
/// The format of the selected date in the title.
/// </summary>
/// <remarks>
/// Defaults to <c>ddd, dd MMM</c>.<br />
/// Defaults to <c>ddd, dd MMM</c>.
/// Supported date formats can be found here: <see href="https://learn.microsoft.com/dotnet/standard/base-types/standard-date-and-time-format-strings"/>.
/// </remarks>
[Parameter] public string TitleDateFormat { get; set; } = "ddd, dd MMM";
Expand All @@ -189,7 +189,7 @@ public DateTime? PickerMonth
/// The function used to disable one or more dates.
/// </summary>
/// <remarks>
/// Defaults to <c>null</c>.<br />
/// Defaults to <c>null</c>.
/// When set, a date will be disabled if the function returns <c>true</c>.
/// </remarks>
[Parameter] public Func<DateTime, bool> IsDateDisabledFunc { get; set; } = _ => false;
Expand Down Expand Up @@ -261,13 +261,13 @@ public DateTime? PickerMonth
var tz = TimeZone ?? TimeZoneInfo.Local;

if (value is DateTime dt)
return dt;
return dt == DateTime.MinValue ? null : dt;

if (value is DateTimeOffset dto)
return TimeZoneInfo.ConvertTime(dto, tz).DateTime;
return dto == DateTimeOffset.MinValue ? null : TimeZoneInfo.ConvertTime(dto, tz).DateTime;

if (value is DateOnly d)
return d.ToDateTime(TimeOnly.MinValue);
return d == DateOnly.MinValue ? null : d.ToDateTime(TimeOnly.MinValue);

throw new NotSupportedException($"Type {typeof(T)} not supported");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,32 @@ public void DateTimePicker_Should_Format_Correctly()
text.Should().Be("03.05.2026 14:30");
}

[Test]
public void DateTimePicker_DateTime_Should_Render_Time()
{
var comp = RenderPicker(
value: new DateTime(2026, 5, 3, 14, 30, 0),
format: "dd.MM.yyyy HH:mm");

comp.Instance.ConvertSetInternal(comp.Instance.Value).Should().Be("03.05.2026 14:30");
}

[Test]
public void DateTimePicker_DateTimeNullable_Should_Render_Empty_When_Null()
{
var comp = RenderPicker<DateTime?>();

comp.Find("input").GetAttribute("value").Should().BeNullOrEmpty();
}

[Test]
public void DateTimePicker_Default_DateTime_Should_Render_Empty()
{
var comp = RenderPicker<DateTime>();

comp.Find("input").GetAttribute("value").Should().BeNullOrEmpty();
}

[Test]
public void DateTimePicker_DateOnly_Should_Not_Render_Time()
{
Expand All @@ -53,8 +79,49 @@ public void DateTimePicker_DateOnly_Should_Not_Render_Time()
comp.Markup.Should().NotContain("mud-picker-time");
}

[Test]
public void DateTimePicker_DateOnly_Should_Render_Date_Only()
{
var comp = RenderPicker(
value: new DateOnly(2026, 5, 3),
format: "dd.MM.yyyy");

comp.Instance.ConvertSetInternal(comp.Instance.Value).Should().Be("03.05.2026");
}

[Test]
public void DateTimePicker_Default_DateOnly_Should_Render_Empty()
{
var comp = RenderPicker<DateOnly>();

comp.Find("input").GetAttribute("value").Should().BeNullOrEmpty();
}

[Test]
public void DateTimePicker_DateOnlyNullable_Should_Render_Empty_When_Null()
{
var comp = RenderPicker<DateOnly?>();

comp.Find("input").GetAttribute("value").Should().BeNullOrEmpty();
}

[Test]
public void DateTimePicker_DateTimeOffset_Should_Convert_Correctly()
{
DateTimeOffset value = new DateTimeOffset(2026, 5, 3, 10, 0, 0, TimeSpan.Zero);

var comp = Context.Render<MudDateTimePicker<DateTimeOffset>>(p => p
.Add(x => x.Value, value)
.Add(x => x.TimeZone, TimeZoneInfo.Utc)
);

var dt = comp.Instance.ToDateTime(value);

dt.Should().Be(new DateTime(2026, 5, 3, 10, 0, 0));
}

[Test]
public void DateTimePicker_DateTimeOffsetNullable_Should_Convert_Correctly()
{
DateTimeOffset? value = new DateTimeOffset(2026, 5, 3, 10, 0, 0, TimeSpan.Zero);

Expand All @@ -68,6 +135,22 @@ public void DateTimePicker_DateTimeOffset_Should_Convert_Correctly()
dt.Should().Be(new DateTime(2026, 5, 3, 10, 0, 0));
}

[Test]
public void DateTimePicker_DateTimeOffsetNullable_Should_Render_Empty_When_Null()
{
var comp = RenderPicker<DateTimeOffset?>();

comp.Find("input").GetAttribute("value").Should().BeNullOrEmpty();
}

[Test]
public void DateTimePicker_Default_DateTimeOffset_Should_Render_Empty()
{
var comp = RenderPicker<DateTimeOffset>();

comp.Find("input").GetAttribute("value").Should().BeNullOrEmpty();
}

[Test]
public async Task DateTimePicker_Input_Change_Should_Update_Value()
{
Expand Down
Loading