Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Select] Fix multiple issues #2840

Merged
merged 6 commits into from
Oct 22, 2024
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
3 changes: 2 additions & 1 deletion examples/Demo/Shared/Pages/Lab/IssueTester.razor
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@

@using FluentUI.Demo.Shared.Pages.List.Select.Examples
<SelectMultiple />
2 changes: 0 additions & 2 deletions examples/Demo/Shared/Pages/List/Listbox/ListboxPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@

<DemoSection Title="Long list with Width and Height" Component="@typeof(ListboxSize)"></DemoSection>

<DemoSection Title="Multiple (not working yet!!)" Component="@typeof(ListboxMultiple)"></DemoSection>

<DemoSection Title="Option template" Component="@typeof(ListboxWithOptionTemplate)"></DemoSection>

<h2 id="documentation">Documentation</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@
SelectedOptions = Data.People.Skip(2).Take(2);
SelectedValue = SelectedOptions.First().PersonId.ToString();
}
}
}
2 changes: 1 addition & 1 deletion examples/Demo/Shared/Shared/EmptyLayout.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@inherits LayoutComponentBase

<div style="overflow: auto;">
<div style="margin: 1.5rem; overflow: auto; height: 800px;">
@Body
</div>
3 changes: 2 additions & 1 deletion src/Core/Components/List/ListComponentBase.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
108 changes: 66 additions & 42 deletions src/Core/Components/List/ListComponentBase.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<TOption>)
// 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<TOption>)
{
Value = null;
await ValueChanged.InvokeAsync(Value);
}
}
else
{
Value = newValue;
await ValueChanged.InvokeAsync(Value);
}
await SelectedOptionChanged.InvokeAsync(SelectedOption);
}
}
}

Expand Down Expand Up @@ -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<TOption>(SelectedOptions);
_selectedOptions = [.. SelectedOptions];
}

if (SelectedOptions == null && Items != null && OptionSelected != null)
Expand Down Expand Up @@ -501,8 +522,8 @@ this is FluentCombobox<TOption> ||

SelectedOption = item;

InternalValue = Value = value;

//InternalValue = Value = value;
InternalValue = value;
await RaiseChangedEventsAsync();
}
}
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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);
Expand Down
Loading