Skip to content

Commit 76c9ffe

Browse files
Pickers: Fix ReadOnly not respected in PickerVariant.Static (#12785)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: danielchalmers <7112040+danielchalmers@users.noreply.github.com>
1 parent 9b6c364 commit 76c9ffe

6 files changed

Lines changed: 63 additions & 0 deletions

File tree

src/MudBlazor.UnitTests/Components/DatePickerTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,23 @@ public async Task CheckReadOnly()
11201120
picker.Date.Should().Be(now);
11211121
}
11221122

1123+
[Test]
1124+
public async Task StaticReadOnly_ShouldNotChangeDate()
1125+
{
1126+
var initialDate = new DateTime(2025, 6, 15);
1127+
var comp = Context.Render<MudDatePicker>(parameters => parameters
1128+
.Add(p => p.PickerVariant, PickerVariant.Static)
1129+
.Add(p => p.ReadOnly, true)
1130+
.Add(p => p.Date, initialDate));
1131+
var picker = comp.Instance;
1132+
1133+
// Try to select a different day - should be blocked by ReadOnly
1134+
await comp.SelectDateAsync("10");
1135+
1136+
// Date should remain unchanged because ReadOnly is true
1137+
picker.Date.Should().Be(initialDate);
1138+
}
1139+
11231140
[Test]
11241141
public async Task CheckDateTimeMinValue()
11251142
{

src/MudBlazor.UnitTests/Components/DateRangePickerTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,24 @@ public void DateRangePicker_CustomClearIcon_Should_BeRenderedInMarkup()
13621362
comp.Markup.Should().Contain(comp.Instance.ClearIcon);
13631363
}
13641364

1365+
[Test]
1366+
public async Task StaticReadOnly_ShouldNotChangeDateRange()
1367+
{
1368+
var initialRange = new DateRange(new DateTime(2025, 6, 10), new DateTime(2025, 6, 20));
1369+
var comp = Context.Render<MudDateRangePicker>(parameters => parameters
1370+
.Add(p => p.PickerVariant, PickerVariant.Static)
1371+
.Add(p => p.ReadOnly, true)
1372+
.Add(p => p.DateRange, initialRange));
1373+
var picker = comp.Instance;
1374+
1375+
// Try to select different days - should be blocked by ReadOnly
1376+
await comp.SelectDateAsync("5", firstOccurrence: true);
1377+
await comp.SelectDateAsync("25", firstOccurrence: true);
1378+
1379+
// DateRange should remain unchanged because ReadOnly is true
1380+
picker.DateRange.Should().Be(initialRange);
1381+
}
1382+
13651383
private sealed class DateRangePickerImpl : MudDateRangePicker
13661384
{
13671385
public DateTime StartOfMonth() => GetCalendarStartOfMonth();

src/MudBlazor.UnitTests/Components/TimePickerTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,5 +380,23 @@ public void TimePicker_CustomClearIcon_Should_BeRenderedInMarkup()
380380

381381
comp.Markup.Should().Contain(comp.Instance.ClearIcon);
382382
}
383+
384+
[Test]
385+
public async Task StaticReadOnly_ShouldNotChangeTime()
386+
{
387+
var initialTime = new TimeSpan(10, 30, 0);
388+
var comp = Context.Render<MudTimePicker>(parameters => parameters
389+
.Add(p => p.PickerVariant, PickerVariant.Static)
390+
.Add(p => p.ReadOnly, true)
391+
.Add(p => p.Time, initialTime));
392+
var picker = comp.Instance;
393+
394+
// Simulate clock stick interaction (as invoked from JS)
395+
await comp.InvokeAsync(() => picker.SelectTimeFromStick(5, false));
396+
397+
// Time should remain unchanged because ReadOnly is true
398+
picker.Time.Should().Be(initialTime);
399+
picker.TimeIntermediate.Should().Be(initialTime);
400+
}
383401
}
384402
}

src/MudBlazor/Components/DatePicker/MudDatePicker.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ protected override string GetDayClasses(int month, DateTime day)
132132

133133
protected override async Task OnDayClickedAsync(DateTime dateTime)
134134
{
135+
if (GetReadOnlyState())
136+
return;
135137
await FocusAsync();
136138
_selectedDate = dateTime;
137139
if (PickerActions == null || AutoClose || PickerVariant == PickerVariant.Static)
@@ -152,6 +154,8 @@ protected override async Task OnDayClickedAsync(DateTime dateTime)
152154
/// <param name="month"></param>
153155
protected override async Task OnMonthSelectedAsync(DateTime month)
154156
{
157+
if (GetReadOnlyState())
158+
return;
155159
await FocusAsync();
156160
PickerMonth = month;
157161
var nextView = GetNextView();
@@ -191,6 +195,8 @@ protected override async Task OnMonthSelectedAsync(DateTime month)
191195
/// <param name="year"></param>
192196
protected override async Task OnYearClickedAsync(int year)
193197
{
198+
if (GetReadOnlyState())
199+
return;
194200
await FocusAsync();
195201
var current = GetMonthStart(0);
196202
var culture = GetCulture();

src/MudBlazor/Components/DatePicker/MudDateRangePicker.razor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ protected override string GetDayClasses(int month, DateTime day)
430430

431431
protected override async Task OnDayClickedAsync(DateTime dateTime)
432432
{
433+
if (GetReadOnlyState())
434+
return;
433435
if (_firstDate == null || _secondDate != null)
434436
{
435437
_secondDate = null;

src/MudBlazor/Components/TimePicker/MudTimePicker.razor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ private string GetMinuteString()
276276

277277
private Task UpdateTimeAsync()
278278
{
279+
if (GetReadOnlyState())
280+
return Task.CompletedTask;
279281
TimeIntermediate = new TimeSpan(_timeSet.Hour, _timeSet.Minute, 0);
280282
if ((PickerVariant == PickerVariant.Static && PickerActions == null) || (PickerActions != null && AutoClose))
281283
{

0 commit comments

Comments
 (0)