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

[Lists]: don't make parameters only be set once #3457

Merged
merged 2 commits into from
Mar 3, 2025
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
80 changes: 37 additions & 43 deletions src/Core/Components/List/FluentCombobox.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace Microsoft.FluentUI.AspNetCore.Components;
public partial class FluentCombobox<TOption> : ListComponentBase<TOption>, IAsyncDisposable where TOption : notnull
{
private const string JAVASCRIPT_FILE = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/List/FluentCombobox.razor.js";
private bool _hasInitializedParameters;

/// <summary />
[Inject]
Expand Down Expand Up @@ -84,61 +83,56 @@ public override async Task SetParametersAsync(ParameterView parameters)
{
parameters.SetParameterProperties(this);

if (!_hasInitializedParameters)
{

var isSetSelectedOption = false;
TOption? newSelectedOption = default;
var isSetSelectedOption = false;
TOption? newSelectedOption = default;

foreach (var parameter in parameters)
foreach (var parameter in parameters)
{
switch (parameter.Name)
{
switch (parameter.Name)
{
case nameof(SelectedOption):
isSetSelectedOption = true;
newSelectedOption = (TOption?)parameter.Value;
break;
default:
break;
}
case nameof(SelectedOption):
isSetSelectedOption = true;
newSelectedOption = (TOption?)parameter.Value;
break;
default:
break;
}
}

if (isSetSelectedOption && !Equals(_currentSelectedOption, newSelectedOption))
if (isSetSelectedOption && !Equals(_currentSelectedOption, newSelectedOption))
{
if (Items != null)
{
if (Items != null)
if (Items.Contains(newSelectedOption))
{
if (Items.Contains(newSelectedOption))
{
_currentSelectedOption = newSelectedOption;
}
else if (OptionSelected != null && newSelectedOption != null && OptionSelected(newSelectedOption))
{
// The selected option might not be part of the Items list. But we can use OptionSelected to compare the current option.
_currentSelectedOption = newSelectedOption;
}
else
{
// If the selected option is not in the list of items, reset the selected option
_currentSelectedOption = SelectedOption = default;
await SelectedOptionChanged.InvokeAsync(SelectedOption);
}
_currentSelectedOption = newSelectedOption;
}
else
else if (OptionSelected != null && newSelectedOption != null && OptionSelected(newSelectedOption))
{
// If Items is null, we don't know if the selected option is in the list of items, so we just set it
// The selected option might not be part of the Items list. But we can use OptionSelected to compare the current option.
_currentSelectedOption = newSelectedOption;
}

// Sync Value from selected option.
// If it is null, we set it to the default value so the attribute is not deleted & the webcomponents don't throw an exception
var value = GetOptionValue(_currentSelectedOption) ?? string.Empty;
if (Value != value)
else
{
Value = value;
await ValueChanged.InvokeAsync(Value);
// If the selected option is not in the list of items, reset the selected option
_currentSelectedOption = SelectedOption = default;
await SelectedOptionChanged.InvokeAsync(SelectedOption);
}
}
_hasInitializedParameters = true;
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;
}

// Sync Value from selected option.
// If it is null, we set it to the default value so the attribute is not deleted & the webcomponents don't throw an exception
var value = GetOptionValue(_currentSelectedOption) ?? string.Empty;
if (Value != value)
{
Value = value;
await ValueChanged.InvokeAsync(Value);
}
}

await base.SetParametersAsync(ParameterView.Empty);
Expand Down
138 changes: 69 additions & 69 deletions src/Core/Components/List/ListComponentBase.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,101 +215,101 @@ public override async Task SetParametersAsync(ParameterView parameters)
{
parameters.SetParameterProperties(this);

if (!_hasInitializedParameters)
if (!Multiple)
{
if (!Multiple)
{
bool isSetSelectedOption = false, isSetValue = false;
TOption? newSelectedOption = default;
string? newValue = null;
bool isSetSelectedOption = false, isSetValue = false;
TOption? newSelectedOption = default;
string? newValue = null;

foreach (var parameter in parameters)
foreach (var parameter in parameters)
{
switch (parameter.Name)
{
switch (parameter.Name)
{
case nameof(SelectedOption):
isSetSelectedOption = true;
newSelectedOption = (TOption?)parameter.Value;
break;
case nameof(Value):
isSetValue = true;
newValue = (string?)parameter.Value;
break;
case nameof(Items):
if (Items is not null && OptionSelected is not null)
{
newSelectedOption = Items.FirstOrDefault(i => OptionSelected?.Invoke(i) == true);
newValue = GetOptionValue(newSelectedOption);
}
break;
default:
break;
}
case nameof(SelectedOption):
isSetSelectedOption = true;
newSelectedOption = (TOption?)parameter.Value;
break;
case nameof(Value):
isSetValue = true;
newValue = (string?)parameter.Value;
break;
case nameof(Items):
if (Items is not null && OptionSelected is not null)
{
newSelectedOption = Items.FirstOrDefault(i => OptionSelected?.Invoke(i) == true);
newValue = GetOptionValue(newSelectedOption);
}
break;
default:
break;
}
}

if (newSelectedOption is not null || newValue is not null || Value is not null)
if (newSelectedOption is not null || newValue is not null || Value is not null)
{
if (isSetSelectedOption && !Equals(_currentSelectedOption, newSelectedOption))
{
if (isSetSelectedOption && !Equals(_currentSelectedOption, newSelectedOption))
if (Items != null)
{
if (Items != null)
if (Items.Contains(newSelectedOption))
{
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);
}
_currentSelectedOption = newSelectedOption;
// Make value follow new selected option
Value = GetOptionValue(_currentSelectedOption);
await ValueChanged.InvokeAsync(Value);
}
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;
// 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 Items is null, we don't know if the selected option is in the list of items, so we just set it
_currentSelectedOption = newSelectedOption;
}
}

if (isSetValue && newValue is null)
if (isSetValue && newValue is null)
{
// Check if one of the Items is selected
if (Items is not null)
{
// Check if one of the Items is selected
if (Items is not null)
newSelectedOption = Items.FirstOrDefault(item => OptionSelected?.Invoke(item) == true);
if (newSelectedOption is not null)
{
newSelectedOption = Items.FirstOrDefault(item => OptionSelected?.Invoke(item) == true);
if (newSelectedOption is not null)
{
_currentSelectedOption = SelectedOption = newSelectedOption;
newValue = GetOptionValue(_currentSelectedOption);
}
_currentSelectedOption = SelectedOption = newSelectedOption;
newValue = GetOptionValue(_currentSelectedOption);
}
}

if (newValue is null)
{
// If the selected option is not in the list of items, reset the selected option
_currentSelectedOption = SelectedOption = default;
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
if (this is not FluentCombobox<TOption>)
{
Value = newValue;
Value = null;
await ValueChanged.InvokeAsync(Value);
}
await SelectedOptionChanged.InvokeAsync(SelectedOption);
}
else
{
Value = newValue;
await ValueChanged.InvokeAsync(Value);
}
await SelectedOptionChanged.InvokeAsync(SelectedOption);
}
}
}

if (!_hasInitializedParameters)
{
if (SelectedOptionExpression is not null)
{
FieldIdentifier = FieldIdentifier.Create(SelectedOptionExpression);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

<style>#myComponent::part(listbox) { z-index: 9995 }</style>
<fluent-combobox id="xxx" current-value="Contoso" position="below" blazor:onchange="1" blazor:elementreference="">
<fluent-option id="xxx" value="Contoso" selected="" aria-selected="true" blazor:onclick="2" blazor:elementreference="">Contoso</fluent-option>
<fluent-combobox id="xxx" current-value="" position="below" blazor:oncomboboxchange="1" blazor:oncontrolinput="2" blazor:elementreference="">
<fluent-option id="xxx" value="Contoso" blazor:onclick="3" aria-selected="false" blazor:elementreference="">Contoso</fluent-option>
</fluent-combobox>
Loading