I'm building a dropdown list that filters based on input. When you click the down arrow it should focus on the first item in the list. The following is a simplified version of the issue I'm getting.
When you enter "a" in the input and then delete it, and afterwards press the down arrow, I get: The given key was not present in the dictionary. Can someone explain why this would happen? Why wouldn't the key be in the dictionary? What stopped it from being added?
<div class="parent" >
<div class="container">
<input class="input" @oninput="FilterIdentifiers" @onkeydown="(e) => HandleKBEvents(e)"/>
<div class="dropdown">
@{
int i = 1;
foreach (var identifier in identifiersUI)
{
<div class="dropdown-item" @key="identifier" tabindex="@i" @ref="refs[identifier]">@identifier</div>
i++;
}
}
</div>
</div>
@code {
private List<string> identifiers = new List<string>
{
"Aaa",
"Aab",
"Aba",
"Aca",
"Baa",
"Bba"
};
private List<string> identifiersUI = new List<string>();
private Dictionary<string, ElementReference> refs = new Dictionary<string, ElementReference>();
protected override async Task OnInitializedAsync()
{
identifiersUI = identifiers;
}
private void FilterIdentifiers(ChangeEventArgs e)
{
string input = e.Value.ToString();
refs.Clear();
identifiersUI = identifiers.Where(s => s.ToUpper().StartsWith(input.ToUpper())).ToList();
}
private void HandleKBEvents(KeyboardEventArgs e)
{
if (e.Code == "ArrowDown")
{
refs[identifiersUI[0]].FocusAsync();
}
}
}
When I change the FilterIdentifiers method to this it does work however. I saw this GitHub Blazor @ref and I thought I would try to only remove the keys that were filtered out to see if that made any difference...and it actually worked. Don't really understand why tho...
private void FilterIdentifiers(ChangeEventArgs e)
{
string input = e.Value.ToString();
var id = identifiers.Where(s => s.ToUpper().StartsWith(input.ToUpper())).ToList();
//remove removed elements from refs
var elements = identifiersUI.Except(id);
identifiersUI = id;
foreach (var element in elements)
{
refs.Remove(element);
}
}