ElementReference to conditionally created element in Blazor

Viewed 1467

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:

enter image description here

Working example with error https://blazorrepl.com/repl/wbueaMPK28hf2NNv09

3 Answers

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;
    }
}

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.

Related