Reputation: 1293
I'm trying to set focus to input control which is conditionally rendered. I'm setting ElementReference
but it's id and context are both null.
<button @onclick="ToggleInput">Show input</button>
@if(showInput) {
<input @ref="inputRef" type="text"/>
}
@code {
private ElementReference inputRef;
private bool showInput;
async void ToggleInput() {
showInput = !showInput;
await inputRef.FocusAsync();
}
}
When I press the button it shows this error in console:
System.InvalidOperationException: ElementReference has not been configured correctly
Full error message:
Working example with error https://blazorrepl.com/repl/wbueaMPK28hf2NNv09
Upvotes: 6
Views: 5733
Reputation: 1970
A slightly cleaner solution:
<button @onclick="ToggleInput">Show input</button>
@if(showInput) {
<input @ref="inputRef" type="text"/>
}
@code {
private ElementReference inputRef;
private bool showInput;
async void ToggleInput() {
showInput = !showInput;
await InvokeAsync(StateHasChanged);
await inputRef.FocusAsync();
}
}
Upvotes: 0
Reputation: 111
It's not the perfect solution either, more like a workaround, but the following worked for me:
<button @onclick="ToggleInput">Show input</button>
@if(showInput) {
<input @ref="inputRef" type="text"/>
}
@code {
private ElementReference inputRef;
private bool showInput;
async void ToggleInput() {
showInput = !showInput;
StateHasChanged();
await Task.Run(() =>
{
if(inputRef.Context != null) inputRef.FocusAsync();
});
}
}
In my tests, the context was never null, so it probably wouldn't need the check. But I prefer that the focus is not set than that an exception would be thrown.
Upvotes: 2
Reputation: 6348
This seems to work and didn't have to be a separate component. I stuck it right on the start page.
<button @onclick="ToggleInput">Show input</button>
@if (showInput)
{
<input @ref="inputRef" type="text" />
}
@code {
private ElementReference inputRef;
private bool showInput;
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (showInput) await inputRef.FocusAsync();
}
void ToggleInput()
{
showInput = !showInput;
}
}
Upvotes: 9
Reputation: 14523
Move the input box to another component. Then you can then hook into the lifecycle of the component and call .FocusAsync
after it has rendered.
https://blazorrepl.com/repl/cluoEsvU59fl8zYM22
Upvotes: 2