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

FluentSelect: Fix ValueChanged fired twice #828

Merged
merged 4 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
2,120 changes: 360 additions & 1,760 deletions examples/Demo/Shared/Microsoft.Fast.Components.FluentUI.xml

Large diffs are not rendered by default.

30 changes: 29 additions & 1 deletion examples/Demo/Shared/Pages/Lab/IssueTester.razor
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
@page "/IssueTester"
@page "/IssueTester"


@inject DataSource Data
<label for="people-listbox">Select a person</label>
<FluentSelect TOption="Person"
Items="@Data.People.WithVeryLongName()"
Id="people-listbox"
Width="200px"
Height="250px"
OptionValue="@(p => p.PersonId.ToString())"
OptionText="@(p => p.LastName + ", " + p.FirstName)"
Value="@SelectedValue"
ValueChanged="@ValueChangedHandler" />

<p>
Selected value: @SelectedValue <br />
</p>


@code {
string? SelectedValue = "4";

async Task ValueChangedHandler(string? value)
{
Console.WriteLine($"Value: {value}");
SelectedValue = value;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@inject DataSource Data

<h6>!!Experimental!!</h6>
<p>All people whose first name starts with a "J" are initialy selected through the <code>OptionSelected</code> (Func delegate) parameter.</p>
<p>All people with a birth year greater than 1990 are disabled through the <code>OptionDisabled</code> (Func delegate) parameter.</p>
Expand All @@ -21,6 +20,11 @@
<p>
Selected value: @SelectedValue <br />
<em>Reflects the value of the first selected option</em><br />
<em><b>
This value is not always accurate as a user can potentially deselect all enabled options. A browser will not return the value
of a disabled item so the last selected non-disabled value will be returned even if it is not selected anymore!
</b>
</em>
</p>
<p>
Selected options: @(SelectedOptions != null ? String.Join(", ", SelectedOptions.Select(i => i.FirstName)) : "")<br />
Expand Down
8 changes: 4 additions & 4 deletions examples/Demo/Shared/Pages/Select/SelectPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
Fluent UI design system.
</p>


<ApiDocumentation Component="typeof(FluentSelect<>)" GenericLabel="TOption" />

<h2>Examples</h2>

<DemoSection Title="Default" Component="@typeof(SelectDefault)"></DemoSection>
Expand All @@ -32,4 +29,7 @@

<DemoSection Title="Multiple items" Component="@typeof(SelectMultiple)"></DemoSection>

<DemoSection Title="Multiple items with selected and disabled options" Component="@typeof(SelectMultipleWithFunctions)"></DemoSection>
<DemoSection Title="Multiple items with selected and disabled options" Component="@typeof(SelectMultipleWithFunctions)"></DemoSection>

<h2>API Documentation</h2>
<ApiDocumentation Component="typeof(FluentSelect<>)" GenericLabel="TOption" />
18 changes: 9 additions & 9 deletions examples/Demo/Shared/SampleData/DataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ public Task<Country[]> GetCountriesAsync()

private readonly static Person[] _people = new[]
{
new Person ( PersonId: 1, FirstName : "Jean", LastName : "Martin", CountryCode : "fr", BirthDate : new DateOnly(1985, 3, 16), Picture: ImageFaces[0] ),
new Person ( PersonId : 2, FirstName : "António", LastName : "Langa", CountryCode : "mz", BirthDate : new DateOnly(1991, 12, 1), Picture: ImageFaces[1] ),
new Person ( PersonId : 3, FirstName : "Julie", LastName : "Smith", CountryCode : "au", BirthDate : new DateOnly(1958, 10, 10), Picture: ImageFaces[2] ),
new Person ( PersonId : 4, FirstName : "Nur", LastName : "Sari", CountryCode : "id", BirthDate : new DateOnly(1922, 4, 27), Picture: ImageFaces[3] ),
new Person ( PersonId : 5, FirstName : "Jose", LastName : "Hernandez", CountryCode : "mx", BirthDate : new DateOnly(2011, 5, 3), Picture: ImageFaces[4] ),
new Person ( PersonId : 6, FirstName : "Bert", LastName : "de Vries", CountryCode : "nl", BirthDate : new DateOnly(1999, 6, 9), Picture: ImageFaces[5] ),
new Person ( PersonId : 7, FirstName : "Jaques", LastName : "Martin", CountryCode : "fr", BirthDate : new DateOnly(2002, 10, 20), Picture: ImageFaces[6] ),
new Person ( PersonId : 8, FirstName : "Elizabeth", LastName : "Johnson", CountryCode : "gb", BirthDate : new DateOnly(1971, 11, 24), Picture: ImageFaces[7] ),
new Person ( PersonId : 9, FirstName : "Jakob", LastName : "Berger", CountryCode : "de", BirthDate : new DateOnly(1971, 4, 21), Picture: string.Empty )
new Person ( PersonId: 1, FirstName : "Jean", LastName : "Martin", CountryCode : "FR", BirthDate : new DateOnly(1985, 3, 16), Picture: ImageFaces[0] ),
vnbaaij marked this conversation as resolved.
Show resolved Hide resolved
new Person ( PersonId : 2, FirstName : "António", LastName : "Langa", CountryCode : "MZ", BirthDate : new DateOnly(1991, 12, 1), Picture: ImageFaces[1] ),
new Person ( PersonId : 3, FirstName : "Julie", LastName : "Smith", CountryCode : "AU", BirthDate : new DateOnly(1958, 10, 10), Picture: ImageFaces[2] ),
new Person ( PersonId : 4, FirstName : "Nur", LastName : "Sari", CountryCode : "ID", BirthDate : new DateOnly(1922, 4, 27), Picture: ImageFaces[3] ),
new Person ( PersonId : 5, FirstName : "Jose", LastName : "Hernandez", CountryCode : "MX", BirthDate : new DateOnly(2011, 5, 3), Picture: ImageFaces[4] ),
new Person ( PersonId : 6, FirstName : "Bert", LastName : "de Vries", CountryCode : "NL", BirthDate : new DateOnly(1999, 6, 9), Picture: ImageFaces[5] ),
new Person ( PersonId : 7, FirstName : "Jaques", LastName : "Martin", CountryCode : "BE", BirthDate : new DateOnly(2002, 10, 20), Picture: ImageFaces[6] ),
new Person ( PersonId : 8, FirstName : "Elizabeth", LastName : "Johnson", CountryCode : "GB", BirthDate : new DateOnly(1971, 11, 24), Picture: ImageFaces[7] ),
new Person ( PersonId : 9, FirstName : "Jakob", LastName : "Berger", CountryCode : "D", BirthDate : new DateOnly(1971, 4, 21), Picture: string.Empty )
};

public class MonthItem
Expand Down
5 changes: 4 additions & 1 deletion examples/Demo/Shared/SampleData/Person.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace FluentUI.Demo.Shared.SampleData;

public record Person(int PersonId, string CountryCode, string FirstName, string LastName, DateOnly BirthDate, string Picture);
public record Person(int PersonId, string CountryCode, string FirstName, string LastName, DateOnly BirthDate, string Picture)
{
public override string ToString() => $"{FirstName} {LastName} ({BirthDate}, {CountryCode})";
}

public class SimplePerson
{
Expand Down
8 changes: 6 additions & 2 deletions src/Core/Components/List/FluentOption.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ protected override Task OnInitializedAsync()

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && Selected && InternalListContext != null && InternalListContext.ValueChanged.HasDelegate)
if (firstRender && Selected &&
InternalListContext != null &&
InternalListContext.ValueChanged.HasDelegate &&
InternalListContext.ListComponent.Multiple)
{
await InternalListContext.ValueChanged.InvokeAsync(Value);
}
Expand All @@ -82,7 +85,8 @@ protected async Task OnSelectHandler()
else
{
if (InternalListContext != null &&
InternalListContext.ValueChanged.HasDelegate)
InternalListContext.ValueChanged.HasDelegate &&
InternalListContext.ListComponent.Items is null)
{
await InternalListContext.ValueChanged.InvokeAsync(Value);
}
Expand Down
23 changes: 12 additions & 11 deletions src/Core/Components/List/ListComponentBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected string? InternalValue

Value = value;
// Raise Changed events in another thread
Task.Run(() => RaiseChangedEventsAsync());
RaiseChangedEventsAsync().ConfigureAwait(false);
}
}
}
Expand Down Expand Up @@ -252,7 +252,7 @@ protected virtual bool GetOptionSelected(TOption item)
{
return false;
}
else if (OptionSelected != null)
else if (OptionSelected != null && _selectedOptions.Contains(item))
{
return OptionSelected.Invoke(item);
}
Expand Down Expand Up @@ -343,7 +343,10 @@ protected virtual async Task OnSelectedItemChangedHandlerAsync(TOption? item)
AddSelectedItem(item);
await RaiseChangedEventsAsync();
}

if (!Equals(item, SelectedOption))
{
SelectedOption = item;
}
}
else
{
Expand Down Expand Up @@ -371,14 +374,12 @@ protected virtual async Task RaiseChangedEventsAsync()
{
await SelectedOptionChanged.InvokeAsync(SelectedOption);
}

if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(InternalValue);
}
}

StateHasChanged();
if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(InternalValue);
StateHasChanged();
}
}

/// <summary />
Expand Down Expand Up @@ -421,7 +422,7 @@ protected virtual async Task RaiseChangedEventsAsync()
}));

// Needed in fluent-listbox and fluent-select with mutliple select enabled
if (this is FluentListbox<TOption> ||
if (this is FluentListbox<TOption> ||
(this is FluentSelect<TOption> && Multiple) ||
(this is FluentAutocomplete<TOption> && Multiple))
{
Expand Down