Skip to content
Merged
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 @@ -25,21 +25,21 @@
</MudItem>

<MudItem xs="12" sm="4">
<MudCheckBox @bind-Value="_multiSelection" Label="MultiSelection" Color="Color.Primary" />
<MudCheckBox @bind-Value="_sticky" Label="Sticky" Color="Color.Primary" />
<MudCheckBox @bind-Value="_nested" Label="Nested" Color="Color.Primary" />
<MudCheckBox @bind-Value="_initiallyExpanded" Label="Initially Expanded" Color="Color.Primary" />
<MudCheckBox @bind-Value="_multiSelection" Label="MultiSelection" Color="Color.Secondary" />
<MudCheckBox @bind-Value="_sticky" Label="Sticky" Color="Color.Secondary" />
<MudCheckBox @bind-Value="_nested" Label="Nested" Color="Color.Secondary" />
<MudCheckBox @bind-Value="_initiallyExpanded" Label="Initially Expanded" Color="Color.Secondary" />
<MudDivider />
<MudText Class="ma-4">Selected Value: @_selectedValue</MudText>
<MudText Class="ma-4">Selected Values: @(_selectedValues == null ? null : string.Join(", ", _selectedValues))</MudText>
</MudItem>
</MudGrid>

@code {
bool _multiSelection = false;
bool _sticky = true;
bool _nested = false;
bool _initiallyExpanded = false;
string? _selectedValue;
IEnumerable<string>? _selectedValues;
private bool _multiSelection = false;
private bool _sticky = true;
private bool _nested = false;
private bool _initiallyExpanded = false;
private string? _selectedValue;
private IEnumerable<string>? _selectedValues;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
}
</MudSelectExtended>

<MudSelectExtended MultiSelectionTextFunc="@(_radioGroup?.Value == 1 ? new Func<List<string>, string?>(GetMultiSelectionText2) : null)" MultiSelection="true" ValuePresenter="_valuePresenter" @bind-Value="stringValue" @bind-SelectedValues="stringValues" T="string" Label="US States" AnchorOrigin="Origin.BottomCenter"
<MudSelectExtended MultiSelectionTextFunc="@(_radioGroup?.Value == 1 ? new Func<List<string>, string?>(GetMultiSelectionText2) : null)" MultiSelection="true" ValuePresenter="_valuePresenter" @bind-Value="_stringValue" @bind-SelectedValues="_stringValues" T="string" Label="US States" AnchorOrigin="Origin.BottomCenter"
ChipCloseable="_chipCloseable" ChipSize="_chipSize" ChipVariant="_chipVariant" NoWrap="_nowrap">
@foreach (var state in states)
{
<MudSelectItemExtended T="string" Value="@state" Text="@state" />
}
</MudSelectExtended>

<MudSelectExtended ItemCollection="states" MultiSelectionTextFunc="@(_radioGroup?.Value == 1 ? new Func<List<string>, string?>(GetMultiSelectionText2) : null)" MultiSelection="true" ValuePresenter="_valuePresenter" @bind-Value="stringValue" @bind-SelectedValues="stringValues" T="string" Label="US States" AnchorOrigin="Origin.BottomCenter"
<MudSelectExtended ItemCollection="states" MultiSelectionTextFunc="@(_radioGroup?.Value == 1 ? new Func<List<string>, string?>(GetMultiSelectionText2) : null)" MultiSelection="true" ValuePresenter="_valuePresenter" @bind-Value="_stringValue" @bind-SelectedValues="_stringValues" T="string" Label="US States" AnchorOrigin="Origin.BottomCenter"
ChipCloseable="_chipCloseable" ChipSize="_chipSize" ChipVariant="_chipVariant" NoWrap="_nowrap">
</MudSelectExtended>

Expand All @@ -38,42 +38,42 @@

<MudItem xs="12" sm="4">
<MudRadioGroup @ref="_radioGroup" T="int" ValueChanged="GroupOptionChanged">
<MudRadio Value="0" Color="Color.Primary">Standard Text</MudRadio>
<MudRadio Value="1" Color="Color.Primary">Customized Text</MudRadio>
<MudRadio Value="2" Color="Color.Primary">Chip</MudRadio>
<MudRadio Value="0" Color="Color.Secondary">Standard Text</MudRadio>
<MudRadio Value="1" Color="Color.Secondary">Customized Text</MudRadio>
<MudRadio Value="2" Color="Color.Secondary">Chip</MudRadio>
</MudRadioGroup>
<MudGrid Class="mt-3 px-4">
<MudItem xs="6">
<MudText Typo="Typo.subtitle2">Value:</MudText>
<MudText Typo="Typo.subtitle2">"</MudText>
<MudText Typo="Typo.body2" Class="pl-4">@stringValue</MudText>
<MudText Typo="Typo.body2" Class="pl-4">@_stringValue</MudText>
<MudText Typo="Typo.subtitle2">"</MudText>
</MudItem>
<MudItem xs="6">
<MudText Typo="Typo.subtitle2">SelectedValues: HashSet&lt;string&gt;</MudText>
<MudText Typo="Typo.subtitle2">{</MudText>
<MudText Typo="Typo.body2" Class="pl-4">@(string.Join(", ", stringValues.Select(x => $"\"{x}\"")))</MudText>
<MudText Typo="Typo.subtitle2">}</MudText>
</MudItem>
</MudGrid>
<MudSwitchM3 @bind-Value="_chipCloseable" Label="Chip Closeable" Color="Color.Primary" />
<MudSwitchM3 @bind-Value="_nowrap" Label="Nowrap" Color="Color.Primary" />
<MudSelectExtended Class="mt-4" ItemCollection="@(Enum.GetValues<Variant>())" @bind-Value="_chipVariant" Label="Chip Variant" Variant="Variant.Outlined" Margin="Margin.Dense" />
<MudSelectExtended Class="mt-4" ItemCollection="@(Enum.GetValues<Size>())" @bind-Value="_chipSize" Label="Chip Size" Variant="Variant.Outlined" Margin="Margin.Dense" />
</MudItem>
</MudGrid>
<MudText Typo="Typo.body2" Class="pl-4">@(string.Join(", ", _stringValues.Select(x => $"\"{x}\"")))</MudText>
<MudText Typo="Typo.subtitle2">}</MudText>
</MudItem>
</MudGrid>
<MudSwitchM3 @bind-Value="_chipCloseable" Label="Chip Closeable" Color="Color.Secondary" />
<MudSwitchM3 @bind-Value="_nowrap" Label="Nowrap" Color="Color.Secondary" />
<MudSelectExtended Class="mt-4" ItemCollection="@(Enum.GetValues<Variant>())" @bind-Value="_chipVariant" Label="Chip Variant" Variant="Variant.Outlined" Margin="Margin.Dense" />
<MudSelectExtended Class="mt-4" ItemCollection="@(Enum.GetValues<Size>())" @bind-Value="_chipSize" Label="Chip Size" Variant="Variant.Outlined" Margin="Margin.Dense" />
</MudItem>
</MudGrid>

@code {
MudRadioGroup<int>? _radioGroup;
ValuePresenter _valuePresenter = ValuePresenter.Text;
string stringValue { get; set; } = "Nothing selected";
IEnumerable<string> stringValues { get; set; } = new HashSet<string>() { "Alaska", "California" };
int? intValue;
IEnumerable<int?> intValues { get; set; } = new HashSet<int?>() { 2, 3 };
bool _chipCloseable = false;
Variant _chipVariant = Variant.Filled;
Size _chipSize = Size.Small;
bool _nowrap;
@code {
private MudRadioGroup<int>? _radioGroup;
private ValuePresenter _valuePresenter = ValuePresenter.Text;
private string _stringValue = "Nothing selected";
private IEnumerable<string> _stringValues = new HashSet<string>() { "Alaska", "California" };
private int? intValue;
private IEnumerable<int?> intValues { get; set; } = new HashSet<int?>() { 2, 3 };
private bool _chipCloseable = false;
private Variant _chipVariant = Variant.Filled;
private Size _chipSize = Size.Small;
private bool _nowrap;

public class Complex
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,54 @@

<MudItem xs="12" sm="4">
<MudStack>
<MudSwitchM3 @bind-Value="_multiselection" Color="Color.Primary" Label="MultiSelection" />
<MudSwitchM3 @bind-Value="_searchBoxAutoFocus" Color="Color.Primary" Label="AutoFocus (SearchBox)" />
<MudSwitchM3 @bind-Value="_searchBoxClearable" Color="Color.Primary" Label="Clearable (SearchBox)" />
<MudSwitchM3 @bind-Value="_multiselection" Color="Color.Secondary" Label="MultiSelection" />
<MudSwitchM3 @bind-Value="_searchBoxAutoFocus" Color="Color.Secondary" Label="AutoFocus (SearchBox)" />
<MudSwitchM3 @bind-Value="_searchBoxClearable" Color="Color.Secondary" Label="Clearable (SearchBox)" />
</MudStack>
</MudItem>
</MudGrid>

<MudGrid Class="mt-8">
<MudItem xs="12">
<MudText Typo="Typo.h6" Class="mb-4">Complex Type with ToStringFunc and Search</MudText>
</MudItem>
<MudItem xs="12" sm="8" Class="d-flex gap-4">
<MudSelectExtended MultiSelection="true"
ItemCollection="TestHouses"
@bind-Value="_selectedHouse"
SearchBox="true"
T="TestHouse"
Label="Houses (Complex Type)"
ToStringFunc="@((TestHouse house) => $"{house.Number} - {house.Name}")"
AnchorOrigin="Origin.BottomCenter"
Variant="Variant.Outlined"
HelperText="Search by number or name (e.g., '1 -' or 'Test3')"
SearchBoxClearable="true" />
</MudItem>

<MudItem xs="12" sm="4">
<MudPaper Class="pa-4" Elevation="0" Outlined="true">
<MudText Typo="Typo.subtitle2" Class="mb-2"><strong>Selected House:</strong></MudText>
@if (_selectedHouse != null)
{
<MudText Typo="Typo.body2">Number: @_selectedHouse.Number</MudText>
<MudText Typo="Typo.body2">Name: @_selectedHouse.Name</MudText>
<MudText Typo="Typo.body2">Postcode: @_selectedHouse.Postcode</MudText>
}
else
{
<MudText Typo="Typo.body2" Color="Color.Secondary">None selected</MudText>
}
</MudPaper>
</MudItem>
</MudGrid>

@code {
bool _multiselection;
bool _searchBoxAutoFocus;
bool _searchBoxClearable;
private string? _selectedState;
private TestHouse? _selectedHouse;

private string[] _states =
{
Expand All @@ -45,6 +81,22 @@
"Washington", "West Virginia", "Wisconsin", "Wyoming",
};

private class TestHouse
{
public int Number { get; set; }
public string? Name { get; set; }
public string? Postcode { get; set; }
}

private List<TestHouse> TestHouses = new()
{
new TestHouse { Number = 1, Name = "Test1", Postcode = "12345" },
new TestHouse { Number = 2, Name = "Test2", Postcode = "54321" },
new TestHouse { Number = 3, Name = "Test3", Postcode = "67890" },
new TestHouse { Number = 4, Name = "Test4", Postcode = "09876" },
new TestHouse { Number = 5, Name = "Test5", Postcode = "11223" },
};

private bool SearchItems(string value, string searchString)
{
if (searchString == "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

<MudItem xs="12" sm="4">
<MudRadioGroup T="SelectAllPosition" @bind-Value="_selectAllPosition">
<MudRadio Value="SelectAllPosition.BeforeSearchBox" Color="Color.Primary">Before Search (Default)</MudRadio>
<MudRadio Value="SelectAllPosition.NextToSearchBox" Color="Color.Primary">Start of the searchbox in the same line</MudRadio>
<MudRadio Value="SelectAllPosition.AfterSearchBox" Color="Color.Primary">After Search</MudRadio>
<MudRadio Value="SelectAllPosition.BeforeSearchBox" Color="Color.Secondary">Before Search (Default)</MudRadio>
<MudRadio Value="SelectAllPosition.NextToSearchBox" Color="Color.Secondary">Start of the searchbox in the same line</MudRadio>
<MudRadio Value="SelectAllPosition.AfterSearchBox" Color="Color.Secondary">After Search</MudRadio>
</MudRadioGroup>
<MudGrid Class="mt-3 px-4">
<MudItem xs="6">
Expand All @@ -33,11 +33,11 @@
</MudItem>
</MudGrid>

@code {
ValuePresenter _valuePresenter = ValuePresenter.Text;
SelectAllPosition _selectAllPosition;
string value { get; set; } = "Nothing selected";
IEnumerable<string> options { get; set; } = new HashSet<string>() { "Alaska", "California" };
@code {
private ValuePresenter _valuePresenter = ValuePresenter.Text;
private SelectAllPosition _selectAllPosition;
private string value { get; set; } = "Nothing selected";
private IEnumerable<string> options { get; set; } = new HashSet<string>() { "Alaska", "California" };

private string[] states =
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ protected internal async Task SearchBoxHandleKeyDownAsync(KeyboardEventArgs obj)
await MudSelectExtended.FocusAsync();
}
break;
case "Escape":
case "Escape":
if (MudSelectExtended != null && MultiSelection == false)
{
await MudSelectExtended.CloseMenu();
Expand Down Expand Up @@ -1783,10 +1783,14 @@ protected internal async ValueTask ScrollToMiddleAsync(MudListItemExtended<T?>?

if (SearchFunc != null)
{
return ItemCollection.Where(x => SearchFunc.Invoke(x, _searchString)).ToList();
return [.. ItemCollection.Where(x => SearchFunc.Invoke(x, _searchString))];
}

return ItemCollection.Where(x => Converter.Convert(x)?.Contains(_searchString, StringComparison.InvariantCultureIgnoreCase) == true).ToList();
var stringValue = new Func<T?, string?>(x =>
ToStringFunc != null ? ToStringFunc(x) : Converter.Convert(x)
);

return [.. ItemCollection.Where(x => stringValue(x)?.Contains(_searchString, StringComparison.InvariantCultureIgnoreCase) == true)];
}

/// <summary>
Expand Down Expand Up @@ -1834,7 +1838,7 @@ protected async Task OnDoubleClickHandler(MouseEventArgs? args, T? itemValue)
///
/// </summary>
protected internal MudListItemExtended<T?>? ActiveItem => _lastActivatedItem;

/// <summary>
///
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@namespace MudExtensions.UnitTests.TestComponents

<MudListExtended @ref="List"
SearchBox="true"
ItemCollection="Houses"
MultiSelection="true"
ToStringFunc="@(house => $"{house!.Number} - {house.Name}")">
</MudListExtended>

@code {
public MudListExtended<TestHouse>? List { get; set; }

public List<TestHouse> Houses = new()
{
new TestHouse { Number = 1, Name = "Test1", Postcode = "12345" },
new TestHouse { Number = 2, Name = "Test2", Postcode = "54321" },
new TestHouse { Number = 3, Name = "Test3", Postcode = "67890" },
};

public class TestHouse
{
public int Number { get; set; }
public string? Name { get; set; }
public string? Postcode { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -363,5 +363,50 @@ public async Task List_SearchChanged_WithNullItemCollection()
var finalItems = comp.FindAll("div.mud-list-item-extended").Count;
finalItems.Should().Be(9);
}


[Test]
public void ListExtended_Search_With_ItemCollection_Should_Use_ToStringFunc()
{
// Arrange
var comp = Context.Render<ListExtendedItemCollectionSearchTest>();
var list = comp.FindComponent<MudListExtended<ListExtendedItemCollectionSearchTest.TestHouse>>().Instance;

list.SearchBox.Should().BeTrue();
list.ItemCollection.Should().HaveCount(3);

// Act - search for "1 - Test1" using reflection to set _searchString
var searchStringField = typeof(MudListExtended<ListExtendedItemCollectionSearchTest.TestHouse>)
.GetField("_searchString", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
searchStringField?.SetValue(list, "1 - Test1");

var result = list.GetSearchedItems();

// Assert - should find item by ToStringFunc format, not class name
result.Should().NotBeNull();
result.Should().HaveCount(1);
result.First().Number.Should().Be(1);
result.First().Name.Should().Be("Test1");
}

[Test]
public void ListExtended_Search_Should_Find_Items_By_Custom_Display_Format_Not_ClassName()
{
// Arrange
var comp = Context.Render<ListExtendedItemCollectionSearchTest>();
var list = comp.FindComponent<MudListExtended<ListExtendedItemCollectionSearchTest.TestHouse>>().Instance;

// Act - search for "Test2" (part of the formatted display, not the class name)
var searchStringField = typeof(MudListExtended<ListExtendedItemCollectionSearchTest.TestHouse>)
.GetField("_searchString", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
searchStringField?.SetValue(list, "Test2");

var result = list.GetSearchedItems();

// Assert
result.Should().HaveCount(1);
result.First().Name.Should().Be("Test2");
result.First().Number.Should().Be(2);
}
}
}
Loading