Blazor的FocusAsync不总是设置焦点

发布于 2025-02-01 20:03:36 字数 1459 浏览 2 评论 0原文

我无法制作.NET 6的大型异步方法。

我可以告诉我,异步仅在组件值不为null时起作用。该模型确保组件值不是零。

模型:

namespace BlazorAppWithService.Models;

public class TagModel
{
    public string? TagName { get; set; } = "";
}

Blazor标记:

<EditForm Model="@newTag" OnValidSubmit="AddTag">
    <InputText @ref="ele "@bind-Value="newTag.TagName"></InputText>
    <button type="submit">Add tag</button>
</EditForm>

此代码:

@code {
    InputText ele;

    private List<TagModel> tagList = new List<TagModel>();

    private TagModel newTag = new TagModel();


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) 
            if (ele.Element != null)
                await ele.Element.Value.FocusAsync();
    }

    private async void AddTag()
    {
        tagList.Add(newTag);
        newTag = new TagModel();
        if (ele.Element != null)
        {
            await ele.Element.Value.FocusAsync();            
        }
    }
}

此代码正确将重点放在第一个渲染上,但是当调用AddTag()方法时,组件并未集中。

FWIW,这也不能定位光标:

<button @onclick="() => ele.Element.Value.FocusAsync()" type="submit">Add tag</button>

大火:使困难的事情变得容易,而且很难!

I can't make .NET 6's Blazor AsyncFocus method work.

Near as I can tell, AsyncFocus only works when a component value isn't null. The model ensures the component value isn't null.

Model:

namespace BlazorAppWithService.Models;

public class TagModel
{
    public string? TagName { get; set; } = "";
}

Blazor markup:

<EditForm Model="@newTag" OnValidSubmit="AddTag">
    <InputText @ref="ele "@bind-Value="newTag.TagName"></InputText>
    <button type="submit">Add tag</button>
</EditForm>

This code:

@code {
    InputText ele;

    private List<TagModel> tagList = new List<TagModel>();

    private TagModel newTag = new TagModel();


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) 
            if (ele.Element != null)
                await ele.Element.Value.FocusAsync();
    }

    private async void AddTag()
    {
        tagList.Add(newTag);
        newTag = new TagModel();
        if (ele.Element != null)
        {
            await ele.Element.Value.FocusAsync();            
        }
    }
}

This code correctly sets focus on the first render, but the component is not focused when the AddTag() method is called.

FWIW, this doesn't position cursor either:

<button @onclick="() => ele.Element.Value.FocusAsync()" type="submit">Add tag</button>

Blazor: Making the hard things easy and the easy things hard!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苯莒 2025-02-08 20:03:36

要解释引擎盖下的focusAsync 正在调用javaScript,但是在这种情况发生后,Blazor正在重新启动。因此,您需要在类似的onFterRenderAsync方法中调用focusAsync

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    await ele.Element.Value.FocusAsync();
}

focustAsync使用JavaScript并不是很明显,但这就是为什么它没有的原因工作。文档中有有关调用JavaScript的文档的摘录:

延迟JavaScript Interop呼叫,直到保证工作的点,覆盖onfterRender {async} lifeCycle
事件。仅在应用程序完全渲染后才调用此事件。

source

To explain what is going on FocusAsync under the hood is calling JavaScript, but Blazor is rerendering after this happens. Therefore, you need to call FocusAsyncin the OnAfterRenderAsync method like so:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    await ele.Element.Value.FocusAsync();
}

Probably it isn't very apparent that FocusAsync uses JavaScript, but this is the reason why it doesn't work. There is this excerpt from the documentation about calling JavaScript:

To delay JavaScript interop calls until a point where such calls are guaranteed to work, override the OnAfterRender{Async} lifecycle
event. This event is only called after the app is fully rendered.

source

听风吹 2025-02-08 20:03:36

对我来说,问题是目标要素不在那里。想象一下这种情况:

if (ShowInput)
{
    <input @ref="MyInput" />
}

@code{
    bool ShowInput { get; set; }
    ElementReference? MyInput { get; set; }
    async Task SomeOperation()
    {
        ShowInput = true;
        //Here, Blazor should render the input, but has not yet. Currently there is no input.
        await MyInput.FocusAsync();
    }
}

因此,我们始终以某种方式呼叫focustAsync完全呈现元素。注意Editform之类的容器组件可能会影响其孩子的渲染行为。 (我认为这是您问题的根源。)

For me, the problem was the target element not being there. Imagine this scenario:

if (ShowInput)
{
    <input @ref="MyInput" />
}

@code{
    bool ShowInput { get; set; }
    ElementReference? MyInput { get; set; }
    async Task SomeOperation()
    {
        ShowInput = true;
        //Here, Blazor should render the input, but has not yet. Currently there is no input.
        await MyInput.FocusAsync();
    }
}

So we should always somehow call FocusAsync after rendering the element completely. Beware that container components like EditForm can affect the rendering behavior of their children. (Which I believe is the source of your problem.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文