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 @@ -578,7 +578,7 @@
return;
_comparer = value;
// Apply comparer and refresh selected values
_selectedValues = new HashSet<T?>(_selectedValues, _comparer);

Check warning on line 581 in src/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'collection' in 'HashSet<T?>.HashSet(IEnumerable<T?> collection, IEqualityComparer<T?>? comparer)'.

Check warning on line 581 in src/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'collection' in 'HashSet<T?>.HashSet(IEnumerable<T?> collection, IEqualityComparer<T?>? comparer)'.
SelectedValues = _selectedValues;
}
}
Expand Down Expand Up @@ -625,7 +625,7 @@

_selectedValues = new HashSet<T?>(set, _comparer);

SelectedValuesChanged.InvokeAsync(new HashSet<T?>(SelectedValues, _comparer)).CatchAndLog();
SelectedValuesChanged.InvokeAsync(_selectedValues).CatchAndLog();
ForceUpdateItems().CatchAndLog();
//Console.WriteLine("SelectedValues setter ended");
}
Expand Down Expand Up @@ -811,7 +811,7 @@
{
DeselectAllItems();
if (ReadValue is not null)
Items.FirstOrDefault(x => x.Value?.Equals(ReadValue) == true).Selected = true;

Check warning on line 814 in src/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
}
}
if ((ReadValue == null && _oldValue != null) || (ReadValue != null && ReadValue.Equals(_oldValue) == false))
Expand Down Expand Up @@ -1246,7 +1246,7 @@
}
else if (MultiSelection == true && SelectedValues?.Contains(item.Value) == true)
{
SelectedValues = SelectedValues.Where(x => x.Equals(item.Value) == false);

Check warning on line 1249 in src/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
await SetValueAndUpdateTextAsync(SelectedValues.LastOrDefault(), false);
item.Selected = false;
_allSelected = GetAllSelectedState();
Expand All @@ -1259,11 +1259,10 @@
DeselectAllItems();
await UpdateComboBoxValueAsync(item.Value, updateText: true, updateSearchString: true);
}
else if (SelectedValues?.Contains(item.Value) != true)
else if (SelectedValues is not null && SelectedValues.Contains(item.Value) != true)
{
await SetValueAndUpdateTextAsync(item.Value, false);
SelectedValues = SelectedValues.Append(item.Value);
await SelectedValuesChanged.InvokeAsync(_selectedValues);
_allSelected = GetAllSelectedState();

//await Task.Delay(1);
Expand Down Expand Up @@ -1395,14 +1394,14 @@
/// </summary>
/// <param name="chip"></param>
/// <returns></returns>
protected async Task ChipClosed(MudChip<T> chip)
protected Task ChipClosed(MudChip<T> chip)
{
if (chip is null || SelectedValues is null)
return;
return Task.CompletedTask;

//SelectedValues = SelectedValues.Where(x => Converter.Set(x)?.ToString() != chip.Value?.ToString());
SelectedValues = SelectedValues.Where(x => x?.Equals(chip.Value) == false);
await SelectedValuesChanged.InvokeAsync(SelectedValues);
return Task.CompletedTask;
}

private bool? _allSelected;
Expand All @@ -1412,26 +1411,19 @@
/// <returns></returns>
protected async Task SelectAllItems()
{
if (_allSelected == null || _allSelected == false)
if (_allSelected != true)
{
SelectedValues = new List<T>();
foreach (var item in Items.Where(x => x.Eligible))
{
item.Selected = true;
SelectedValues = SelectedValues.Append(item.Value);
}
await SelectedValuesChanged.InvokeAsync(SelectedValues);
var eligibleItems = Items.Where(x => x.Eligible).ToList();
foreach (var item in eligibleItems) item.Selected = true;
SelectedValues = [.. eligibleItems.Select(x => x.Value)];
await SetValueAndUpdateTextAsync(SelectedValues.LastOrDefault(), false);
_allSelected = true;
}
else
{
foreach (var item in Items.Where(x => x.Selected))
{
item.Selected = false;
}
var selectedItems = Items.Where(x => x.Selected).ToList();
foreach (var item in selectedItems) item.Selected = false;
SelectedValues = new HashSet<T?>(_comparer);
await SelectedValuesChanged.InvokeAsync(SelectedValues);
_allSelected = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@namespace MudExtensions.UnitTests.TestComponents
<MudPopoverProvider></MudPopoverProvider>

<MudComboBox T="string" MultiSelection ChipCloseable InputPresenter="ValuePresenter.Chip"
SelectedValues=@_selectedValues
SelectedValuesChanged=@SelectedValuesChanged>
<MudComboBoxItem T="string" Value="@("A")">A</MudComboBoxItem>
<MudComboBoxItem T="string" Value="@("B")">B</MudComboBoxItem>
<MudComboBoxItem T="string" Value="@("C")">C</MudComboBoxItem>
</MudComboBox>

@code {
IEnumerable<string> _selectedValues = new HashSet<string> { "A", "B" };
public int Count { get; private set; }

Task SelectedValuesChanged(IEnumerable<string> selectedValues)
{
_selectedValues = selectedValues;
Count++;
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@namespace MudExtensions.UnitTests.TestComponents
<MudPopoverProvider></MudPopoverProvider>

<MudComboBox T="string" MultiSelection SelectAll
SelectedValues=@_selectedValues
SelectedValuesChanged=@SelectedValuesChanged>
@foreach (var character in guids)
{
<MudComboBoxItem T="string" Value="@character">@character</MudComboBoxItem>
}
</MudComboBox>

@code {
IEnumerable<string> _selectedValues = [];
public int Count { get; private set; }
string[] guids = [.. Enumerable.Range(0, 1000).Select(_ => Guid.NewGuid().ToString())];

Task SelectedValuesChanged(IEnumerable<string> selectedValues)
{
_selectedValues = selectedValues;
Count++;
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@namespace MudExtensions.UnitTests.TestComponents
<MudPopoverProvider></MudPopoverProvider>

<MudComboBox T="string" MultiSelection
SelectedValues=@_selectedValues
SelectedValuesChanged=@SelectedValuesChanged>
<MudComboBoxItem T="string" Value="@("A")">A</MudComboBoxItem>
<MudComboBoxItem T="string" Value="@("B")">B</MudComboBoxItem>
<MudComboBoxItem T="string" Value="@("C")">C</MudComboBoxItem>
</MudComboBox>

@code {
IEnumerable<string> _selectedValues = [];
public int Count { get; private set; }

Task SelectedValuesChanged(IEnumerable<string> selectedValues)
{
_selectedValues = selectedValues;
Count++;
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,77 @@ public void MultiSelect_SelectAll()
combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet<string>());
}

/// <summary>
/// When SelectAll is enabled, selecting all items must invoke SelectedValuesChanged exactly once.
/// </summary>
[Test]
public void MultiSelect_SelectAllEnabled_SelectedValuesChangedOnce()
{
var comp = Context.Render<ComboBoxMultiSelectSelectAllEnabledSelectedValuesChanged>();
var combobox = comp.FindComponent<MudComboBox<string>>();
var menu = comp.Find("div.mud-popover");
var input = combobox.Find("div.mud-input-control");
input.Click();
comp.WaitForAssertion(() => menu.ClassList.Should().Contain("mud-popover-open"));

comp.FindAll("div.mud-combobox-item")[0].Click();

comp.WaitForAssertion(() => comp.Instance.Count.Should().Be(1));
combobox.Instance.SelectedValues.Should().HaveCount(1000);
}
/// <summary>
/// Deselecting all items after selecting all must invoke SelectedValuesChanged exactly once more.
/// </summary>
[Test]
public void MultiSelect_SelectAllEnabled_DeselectAll_SelectedValuesChangedOnce()
{
var comp = Context.Render<ComboBoxMultiSelectSelectAllEnabledSelectedValuesChanged>();
var combobox = comp.FindComponent<MudComboBox<string>>();
var menu = comp.Find("div.mud-popover");
combobox.Find("div.mud-input-control").Click();
comp.WaitForAssertion(() => menu.ClassList.Should().Contain("mud-popover-open"));
comp.FindAll("div.mud-combobox-item")[0].Click();
comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().HaveCount(1000));

comp.FindAll("div.mud-combobox-item")[0].Click();

comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().BeEmpty());
comp.Instance.Count.Should().Be(2);
}

/// <summary>
/// Selecting a single item in multi selection must invoke SelectedValuesChanged exactly once.
/// </summary>
[Test]
public void MultiSelect_SelectOneItem_SelectedValuesChangedOnce()
{
var comp = Context.Render<ComboBoxMultiSelectSelectOneSelectedValuesChanged>();
var combobox = comp.FindComponent<MudComboBox<string>>();
var menu = comp.Find("div.mud-popover");
combobox.Find("div.mud-input-control").Click();
comp.WaitForAssertion(() => menu.ClassList.Should().Contain("mud-popover-open"));

comp.FindAll("div.mud-combobox-item")[0].Click();

comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().BeEquivalentTo(new[] { "A" }));
comp.Instance.Count.Should().Be(1);
}

/// <summary>
/// Closing a chip must invoke SelectedValuesChanged exactly once.
/// </summary>
[Test]
public void MultiSelect_ChipClosed_SelectedValuesChangedOnce()
{
var comp = Context.Render<ComboBoxMultiSelectChipCloseSelectedValuesChanged>();
var combobox = comp.FindComponent<MudComboBox<string>>();

comp.Find("button.mud-chip-close-button").Click();

comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().HaveCount(1));
comp.Instance.Count.Should().Be(1);
}

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