Skip to content

Commit

Permalink
fix(module:select): Set parameters asynchronously
Browse files Browse the repository at this point in the history
This commit adds the AntInputComponentBase.OnValueChangeAsync method and updates the Select module to use OnParametersSetAsync instead of OnParametersSet with the new OnValueChangeAsync. This change ensures that exceptions thrown from user event callback handlers will be caught as they now have an ambient Task instance to report the exceptions on.
  • Loading branch information
WoogaAndrew committed May 27, 2024
1 parent 72a195a commit 75d1a61
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 15 deletions.
9 changes: 9 additions & 0 deletions components/core/Base/AntInputComponentBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,15 @@ protected virtual void OnValueChange(TValue value)
{
}

/// <summary>
/// When this method is called, Value is only has been modified, but the ValueChanged is not triggered, so the outside bound Value is not changed.
/// </summary>
/// <param name="value"></param>
protected virtual Task OnValueChangeAsync(TValue value)
{
return Task.CompletedTask;
}

/// <summary>
/// When this method is called, Value and CurrentValue have been modified, and the ValueChanged has been triggered, so the outside bound Value is changed.
/// </summary>
Expand Down
26 changes: 11 additions & 15 deletions components/select/Select.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ protected override void OnInitialized()
base.OnInitialized();
}

protected override void OnParametersSet()
protected override async Task OnParametersSetAsync()
{
EvaluateDataSourceChange();
if (SelectOptions == null)
Expand All @@ -433,9 +433,9 @@ protected override void OnParametersSet()
EditContext?.NotifyFieldChanged(FieldIdentifier);
}

OnValueChange(_selectedValue);
await OnValueChangeAsync(_selectedValue);
}
base.OnParametersSet();
await base.OnParametersSetAsync();
}

private void EvaluateDataSourceChange()
Expand Down Expand Up @@ -522,12 +522,12 @@ internal async Task ProcessSelectedSelectOptions()
{
if (LastValueBeforeReset is not null)
{
OnValueChange(LastValueBeforeReset);
await OnValueChangeAsync(LastValueBeforeReset);
LastValueBeforeReset = default;
}
else
{
OnValueChange(Value);
await OnValueChangeAsync(Value);
}
}
else
Expand Down Expand Up @@ -1078,17 +1078,14 @@ protected virtual string GetLabel(TItem item)
/// </summary>
internal TItemValue LastValueBeforeReset { get; set; }

/// <summary>
/// The Method is called every time if the value of the @bind-Value was changed by the two-way binding.
/// </summary>
protected override void OnValueChange(TItemValue value)
protected override async Task OnValueChangeAsync(TItemValue value)
{
if (!_optionsHasInitialized) // This is important because otherwise the initial value is overwritten by the EventCallback of ValueChanged and would be NULL.
return;

if (!_isValueEnum && !TypeDefaultExistsAsSelectOption && EqualityComparer<TItemValue>.Default.Equals(value, default))
{
_ = InvokeAsync(() => OnInputClearClickAsync(new()));
await InvokeAsync(() => OnInputClearClickAsync(new()));
return;
}

Expand All @@ -1103,21 +1100,20 @@ protected override void OnValueChange(TItemValue value)

if (!AllowClear)
{
_ = TrySetDefaultValueAsync();
await TrySetDefaultValueAsync();
}
else
{
//Reset value if not found - needed if value changed
//outside of the component
_ = InvokeAsync(() => OnInputClearClickAsync(new()));
await InvokeAsync(() => OnInputClearClickAsync(new()));
}
return;
}

if (result.IsDisabled)
{
_ = TrySetDefaultValueAsync();

await TrySetDefaultValueAsync();
return;
}

Expand All @@ -1128,7 +1124,7 @@ protected override void OnValueChange(TItemValue value)
if (HideSelected)
result.IsHidden = true;

ValueChanged.InvokeAsync(result.Value);
await ValueChanged.InvokeAsync(result.Value);
}

/// <summary>
Expand Down
26 changes: 26 additions & 0 deletions tests/AntDesign.Tests/Select/Select.Value.Tests.razor
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,32 @@
input.GetAttribute("value").Should().BeEmpty();
}

[Fact] // Issue: #3875
public void Exceptions_thrown_from_Event_Callbacks_are_caught()
{
//Arrange
JSInterop.Setup<AntDesign.JsInterop.DomRect>(JSInteropConstants.GetBoundingClientRect, _ => true)
.SetResult(new AntDesign.JsInterop.DomRect());
Func<int, Task> ValueChanged = async v => await Task.FromException(new NotImplementedException());
var cut = Render<AntDesign.Select<int, Person>>(
@<AntDesign.Select DataSource="@_persons"
LabelName="@nameof(Person.Name)"
ValueName="@nameof(Person.Id)"
Value="0"
ValueChanged="@ValueChanged"
AllowClear="false"
>
</AntDesign.Select>
);
Action setParametersAction = () =>
// Act
cut.SetParametersAndRender(parameters => parameters.Add(p => p.Value, _persons.Count - 1)
);

// Assert
setParametersAction.Should().Throw<NotImplementedException>();
}

/*
[Theory]
[MemberData(nameof(AllowClearWithValueOnClearTheory))]
Expand Down

0 comments on commit 75d1a61

Please sign in to comment.