diff --git a/examples/Demo/Shared/Pages/Lab/IssueTester.razor b/examples/Demo/Shared/Pages/Lab/IssueTester.razor index 5f282702bb..d230efc4f4 100644 --- a/examples/Demo/Shared/Pages/Lab/IssueTester.razor +++ b/examples/Demo/Shared/Pages/Lab/IssueTester.razor @@ -1 +1,2 @@ - \ No newline at end of file +@using FluentUI.Demo.Shared.Pages.List.Select.Examples + diff --git a/examples/Demo/Shared/Pages/List/Listbox/ListboxPage.razor b/examples/Demo/Shared/Pages/List/Listbox/ListboxPage.razor index 3198bdb614..68a408ea84 100644 --- a/examples/Demo/Shared/Pages/List/Listbox/ListboxPage.razor +++ b/examples/Demo/Shared/Pages/List/Listbox/ListboxPage.razor @@ -31,8 +31,6 @@ - -

Documentation

diff --git a/examples/Demo/Shared/Pages/List/Select/Examples/SelectMultiple.razor b/examples/Demo/Shared/Pages/List/Select/Examples/SelectMultiple.razor index 248ec71725..1a3a2856a5 100644 --- a/examples/Demo/Shared/Pages/List/Select/Examples/SelectMultiple.razor +++ b/examples/Demo/Shared/Pages/List/Select/Examples/SelectMultiple.razor @@ -32,4 +32,4 @@ SelectedOptions = Data.People.Skip(2).Take(2); SelectedValue = SelectedOptions.First().PersonId.ToString(); } -} \ No newline at end of file +} diff --git a/examples/Demo/Shared/Shared/EmptyLayout.razor b/examples/Demo/Shared/Shared/EmptyLayout.razor index 63af0890be..843532af45 100644 --- a/examples/Demo/Shared/Shared/EmptyLayout.razor +++ b/examples/Demo/Shared/Shared/EmptyLayout.razor @@ -1,5 +1,5 @@ @inherits LayoutComponentBase -
+
@Body
diff --git a/src/Core/Components/List/ListComponentBase.razor b/src/Core/Components/List/ListComponentBase.razor index 19fb3b7ef4..a736ee2571 100644 --- a/src/Core/Components/List/ListComponentBase.razor +++ b/src/Core/Components/List/ListComponentBase.razor @@ -30,7 +30,8 @@ Value="@GetOptionValue(item)" Selected="@GetOptionSelected(item)" Disabled="@(GetOptionDisabled(item) ?? false)" - OnSelect="@OnSelectCallback(item)"> + OnSelect="@OnSelectCallback(item)" + aria-selected="@(GetOptionSelected(item) ? "true" : "false")"> @if (OptionTemplate is not null) { @OptionTemplate(item) diff --git a/src/Core/Components/List/ListComponentBase.razor.cs b/src/Core/Components/List/ListComponentBase.razor.cs index 51caceb484..9fa23b31eb 100644 --- a/src/Core/Components/List/ListComponentBase.razor.cs +++ b/src/Core/Components/List/ListComponentBase.razor.cs @@ -2,13 +2,13 @@ // MIT License - Copyright (c) Microsoft Corporation. All rights reserved. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Web; using Microsoft.FluentUI.AspNetCore.Components.Extensions; using Microsoft.FluentUI.AspNetCore.Components.Utilities; using Microsoft.JSInterop; -using System.Diagnostics.CodeAnalysis; namespace Microsoft.FluentUI.AspNetCore.Components; @@ -209,57 +209,78 @@ public override async Task SetParametersAsync(ParameterView parameters) isSetValue = true; newValue = (string?)parameter.Value; break; + case nameof(Items): + if (Items is not null) + { + newSelectedOption = Items.FirstOrDefault(i => OptionSelected?.Invoke(i) == true); + newValue = GetOptionValue(newSelectedOption); + } + break; default: break; } } - if (isSetSelectedOption && !Equals(_currentSelectedOption, newSelectedOption)) + if (newSelectedOption is not null || newValue is not null || Value is not null) { - if (Items != null) + if (isSetSelectedOption && !Equals(_currentSelectedOption, newSelectedOption)) { - if (Items.Contains(newSelectedOption)) + if (Items != null) { - _currentSelectedOption = newSelectedOption; - // Make value follow new selected option - Value = GetOptionValue(_currentSelectedOption); + if (Items.Contains(newSelectedOption)) + { + _currentSelectedOption = newSelectedOption; + // Make value follow new selected option + Value = GetOptionValue(_currentSelectedOption); + await ValueChanged.InvokeAsync(Value); + } + else + { + // If the selected option is not in the list of items, reset the selected option + _currentSelectedOption = SelectedOption = default; + // and also reset the value + Value = null; + await SelectedOptionChanged.InvokeAsync(SelectedOption); + } } else { - // If the selected option is not in the list of items, reset the selected option - _currentSelectedOption = SelectedOption = default; - // and also reset the value - Value = null; - await SelectedOptionChanged.InvokeAsync(SelectedOption); + // If Items is null, we don't know if the selected option is in the list of items, so we just set it + _currentSelectedOption = newSelectedOption; } } - else - { - // If Items is null, we don't know if the selected option is in the list of items, so we just set it - _currentSelectedOption = newSelectedOption; - } - } - else if (isSetValue && Items != null && GetOptionValue(_currentSelectedOption) != newValue) - { - newSelectedOption = Items.FirstOrDefault(item => GetOptionValue(item) == newValue); - if (newSelectedOption != null) - { - _currentSelectedOption = SelectedOption = newSelectedOption; - } - else + if (isSetValue && newValue is null) { - // If the selected option is not in the list of items, reset the selected option - _currentSelectedOption = SelectedOption = default; - if (this is not FluentCombobox) + // Check if one of the Items is selected + if (Items is not null) { - Value = null; - await ValueChanged.InvokeAsync(Value); + newSelectedOption = Items.FirstOrDefault(item => OptionSelected?.Invoke(item) == true); + if (newSelectedOption is not null) + { + _currentSelectedOption = SelectedOption = newSelectedOption; + newValue = GetOptionValue(_currentSelectedOption); + } } - } - await SelectedOptionChanged.InvokeAsync(SelectedOption); + if (newValue is null) + { + // If the selected option is not in the list of items, reset the selected option + _currentSelectedOption = SelectedOption = default; + if (this is not FluentCombobox) + { + Value = null; + await ValueChanged.InvokeAsync(Value); + } + } + else + { + Value = newValue; + await ValueChanged.InvokeAsync(Value); + } + await SelectedOptionChanged.InvokeAsync(SelectedOption); + } } } @@ -323,9 +344,9 @@ protected override void OnParametersSet() if (Multiple) { - if (SelectedOptions != null && _selectedOptions != SelectedOptions) + if (SelectedOptions != null && SelectedOptions.Any() && _selectedOptions != SelectedOptions) { - _selectedOptions = new List(SelectedOptions); + _selectedOptions = [.. SelectedOptions]; } if (SelectedOptions == null && Items != null && OptionSelected != null) @@ -501,8 +522,8 @@ this is FluentCombobox || SelectedOption = item; - InternalValue = Value = value; - + //InternalValue = Value = value; + InternalValue = value; await RaiseChangedEventsAsync(); } } @@ -515,7 +536,10 @@ protected virtual async Task RaiseChangedEventsAsync() { if (SelectedOptionsChanged.HasDelegate) { - await SelectedOptionsChanged.InvokeAsync(_selectedOptions); + if (_selectedOptions.Count != 0) + { + await SelectedOptionsChanged.InvokeAsync(_selectedOptions); + } } } else @@ -525,9 +549,6 @@ protected virtual async Task RaiseChangedEventsAsync() await SelectedOptionChanged.InvokeAsync(SelectedOption); } } - - // Calling ValueChanged is now done through FluentInputBase.SetCurrentValueAsync - //StateHasChanged(); } protected virtual async Task OnKeydownHandlerAsync(KeyboardEventArgs e) @@ -536,7 +557,10 @@ protected virtual async Task OnKeydownHandlerAsync(KeyboardEventArgs e) { return; } - + if (e.ShiftKey == true || e.AltKey == true || e.CtrlKey == true) + { + return; + } // This delay is needed for WASM to be able to get the updated value of the active descendant. // Without it, the value sometimes lags behind and you then need two keypresses to move to the next/prev option. await Task.Delay(1);