Move the SelectedAccount = Accounts.FirstOrDefault(...) lookup from OnInitialized to OnParametersSet so the preselection tracks the Accounts list arriving asynchronously (every caller now passes [] first and hydrates after an await). Idempotent — the OnSelectedChanged callback path returns the same AccountId back and the parent re-render lookup finds the same account. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
39 lines
No EOL
1.4 KiB
C#
39 lines
No EOL
1.4 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.FluentUI.AspNetCore.Components;
|
|
using Schaad.Accounting.Models;
|
|
|
|
namespace Schaad.Accounting.UI.Components.Pages.Controls;
|
|
|
|
public partial class AccountSelector : ComponentBase
|
|
{
|
|
[Parameter] public required string? AccountId { get; set; }
|
|
|
|
[Parameter] public required IReadOnlyList<Account> Accounts { get; set; }
|
|
|
|
[Parameter] public EventCallback<string> AccountIdChanged { get; set; }
|
|
|
|
private Account? SelectedAccount { get; set; }
|
|
|
|
// OnParametersSet, not OnInitialized: OnInitialized fires once, but callers now
|
|
// pass an empty Accounts list on first render and hydrate it after an await.
|
|
// OnParametersSet re-runs the lookup whenever Accounts or AccountId change, so the
|
|
// preselection tracks late-arriving data.
|
|
protected override void OnParametersSet()
|
|
{
|
|
SelectedAccount = Accounts.FirstOrDefault(account => account.Id == AccountId);
|
|
}
|
|
|
|
private async Task OnSearchAsync(OptionsSearchEventArgs<Account> e)
|
|
{
|
|
e.Items = Accounts.Where(i => i.Name.Contains(e.Text, StringComparison.OrdinalIgnoreCase))
|
|
.OrderBy(i => i.Name);
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
public async Task OnSelectedChanged(IEnumerable<Account>? s)
|
|
{
|
|
SelectedAccount = s?.FirstOrDefault();
|
|
AccountId = SelectedAccount?.Id;
|
|
await AccountIdChanged.InvokeAsync(AccountId);
|
|
}
|
|
} |