【问题标题】:Can I set the focus for the first element in a Blazor modal?我可以为 Blazor 模式中的第一个元素设置焦点吗?
【发布时间】:2022-12-03 03:07:48
【问题描述】:

我在 Blazor(服务器应用程序)中打开一个包含字符串数组的模式。一切都在代码方面有效,但我必须单击第一个元素才能设置焦点(这些是序列号,可以用扫描仪读取)。之后,随着扫描的继续,每次扫描后焦点都会移动。我希望在模式打开时聚焦第一个元素,这样无需单击第一个元素即可开始扫描。

这是模态设置”

<Modal @ref="modalMultipleSerialNumbers" Title="Add/Change Multiple Serial Numbers" UseStaticBackdrop="true" Size="ModalSize.ExtraLarge">
<BodyTemplate>
    @for (var i = 0; i < SD.MaxNumberOfMultiples; i++)
    {
        var count = i; // using i doesn't work.  Has to be stored in a local variable to use bind.'
        <input @bind="@MulipleSerialNumbers[count]" class="col-4 m-1" />
    }
</BodyTemplate>
<FooterTemplate>
    <Button Color="ButtonColor.Secondary" @onclick="OnClearModalClick">Clear list of Serial Numbers</Button>
    <Button Color="ButtonColor.Primary" @onclick="OnSaveModalClick">Save list of Serial Numbers</Button>
</FooterTemplate>

我确实尝试过:

<input @bind="@MulipleSerialNumbers[count]" autofocus="true" class="col-4 m-1" />

但它没有改变任何东西。

感谢您的观看!

【问题讨论】:

    标签: blazor blazor-server-side


    【解决方案1】:

    若要在 Blazor 中将焦点设置在元素上,可以使用 @ref 属性在代码中引用该元素,然后对该元素调用 FocusAsync() 方法以将焦点设置到它。

    下面是一个示例,说明如何在 Blazor 的模式中将焦点设置在输入元素上:

    @page "/modal-example"
    
    <Modal @ref="modalMultipleSerialNumbers" Title="Add/Change Multiple Serial Numbers" UseStaticBackdrop="true" Size="ModalSize.ExtraLarge">
        <BodyTemplate>
            @for (var i = 0; i < SD.MaxNumberOfMultiples; i++)
            {
                var count = i; // using i doesn't work.  Has to be stored in a local variable to use bind.'
                <input @ref="@inputElements[count]" @bind="@MulipleSerialNumbers[count]" class="col-4 m-1" />
            }
        </BodyTemplate>
        <FooterTemplate>
            <Button Color="ButtonColor.Secondary" @onclick="OnClearModalClick">Clear list of Serial Numbers</Button>
            <Button Color="ButtonColor.Primary" @onclick="OnSaveModalClick">Save list of Serial Numbers</Button>
        </FooterTemplate>
    </Modal>
    
    @code {
        private IEnumerable<IInputElement> inputElements;
    
        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                // Set focus to the first input element in the modal
                await inputElements.First().FocusAsync();
            }
        }
    }
    

    在此示例中,我们使用 @ref 属性来引用模式中的每个输入元素,并将这些引用存储在名为 inputElements 的 IEnumerable 字段中。然后,我们使用 OnAfterRenderAsync() 方法在首次呈现模态时将焦点设置到模态中的第一个输入元素。

    您可以在实现 IInputElement 接口的任何元素上调用 FocusAsync() 方法,其中包括输入元素,例如 &lt;input&gt;&lt;select&gt;&lt;textarea&gt;。这允许你将焦点设置在 Blazor 应用程序中的任何元素上。

    【讨论】:

    • 你的解决方案对我来说很有意义,但我有一些问题。我无法使用 IEnumerable,因为它不允许我使用 [] 进行访问。我将其转换为 IList 并解决了该问题。我现在找不到 IInputElement。这是在什么命名空间?我试过几个程序集参考,但找不到合适的。
    • 你可以试试这个@using Microsoft.AspNetCore.Components
    • 它声称也不存在。我已经能够修复错误,但我不得不使用 JavaScript 作为焦点。我已经在答案中发布了我的修复程序。我会使用你能找到的任何其他东西,因为我更喜欢将它保留在 C# 中,但现在,我的回答解决了它。
    【解决方案2】:

    所以,我不得不使用 JavaScript 来解决这个问题。

    模式更改如下:

    <Modal @ref="modalMultipleSerialNumbers" Title="Add/Change Multiple Serial Numbers" UseStaticBackdrop="true" Size="ModalSize.ExtraLarge">
    <BodyTemplate>
        <input id="focusElement" @bind="@MulipleSerialNumbers[0]" class="col-4 m-1" />
        @for (var i = 1; i < SD.MaxNumberOfMultiples; i++)
        {
            var count = i; // using i in the next statement doesn't work.  Has to be stored in a local variable to use bind.
            <input @bind="@MulipleSerialNumbers[count]" class="col-4 m-1" />
        }
    </BodyTemplate>
    <FooterTemplate>
        <Button Color="ButtonColor.Secondary" @onclick="OnClearModalClick">Clear list of Serial Numbers</Button>
        <Button Color="ButtonColor.Primary" @onclick="OnSaveModalClick">Save list of Serial Numbers</Button>
    </FooterTemplate>
    

    这允许我在第一个元素上放置一个 id。

    然后,在显示模态的代码中:

    private async Task OnShowModalClick()
    {
        await modalMultipleSerialNumbers?.ShowAsync();
        Thread.Sleep(250); //had to sleep for a quarter second to allow the modal to render.
        await _jsRuntime.InvokeVoidAsync("FocusElement");
    }
    

    并且只是为了完成:

    function FocusElement() {
    document.getElementById("focusElement").focus();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 2020-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多