fix(module: select): Set parameters asynchronously (#3912)

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.
This commit is contained in:
WoogaAndrew 2024-06-19 17:06:12 +02:00 коммит произвёл GitHub
Родитель 4dc471546f
Коммит 4e76924eac
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 46 добавлений и 15 удалений

Просмотреть файл

@ -282,6 +282,15 @@ namespace AntDesign
{
}
/// <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>

Просмотреть файл

@ -412,7 +412,7 @@ namespace AntDesign
base.OnInitialized();
}
protected override void OnParametersSet()
protected override async Task OnParametersSetAsync()
{
EvaluateDataSourceChange();
if (SelectOptions == null)
@ -433,9 +433,9 @@ namespace AntDesign
EditContext?.NotifyFieldChanged(FieldIdentifier);
}
OnValueChange(_selectedValue);
await OnValueChangeAsync(_selectedValue);
}
base.OnParametersSet();
await base.OnParametersSetAsync();
}
private void EvaluateDataSourceChange()
@ -522,12 +522,12 @@ namespace AntDesign
{
if (LastValueBeforeReset is not null)
{
OnValueChange(LastValueBeforeReset);
await OnValueChangeAsync(LastValueBeforeReset);
LastValueBeforeReset = default;
}
else
{
OnValueChange(Value);
await OnValueChangeAsync(Value);
}
}
else
@ -1078,17 +1078,14 @@ namespace AntDesign
/// </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;
}
@ -1103,21 +1100,20 @@ namespace AntDesign
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;
}
@ -1128,7 +1124,7 @@ namespace AntDesign
if (HideSelected)
result.IsHidden = true;
ValueChanged.InvokeAsync(result.Value);
await ValueChanged.InvokeAsync(result.Value);
}
/// <summary>

Просмотреть файл

@ -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))]