ElementReference 对 Blazor 中有条件创建的元素

ElementReference to conditionally created element in Blazor

我正在尝试将焦点设置到有条件呈现的输入控件。我正在设置 ElementReference 但它的 id 和上下文都是空的。

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

当我按下按钮时,它在控制台中显示此错误:

System.InvalidOperationException: ElementReference has not been configured correctly

完整的错误信息:

错误的工作示例https://blazorrepl.com/repl/wbueaMPK28hf2NNv09

将输入框移动到另一个组件。然后你可以挂钩到组件的生命周期并在它呈现后调用 .FocusAsync

https://blazorrepl.com/repl/cluoEsvU59fl8zYM22

这似乎可行,而且不必是一个单独的组件。我把它贴在了起始页上。

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

这也不是完美的解决方案,更像是一种解决方法,但以下方法对我有用:

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

在我的测试中,上下文从不为空,因此它可能不需要检查。但我更喜欢不设置焦点而不是抛出异常。