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:
Родитель
4dc471546f
Коммит
4e76924eac
|
@ -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))]
|
||||
|
|
Загрузка…
Ссылка в новой задаче