Blazor Server模态框如何设置首个输入元素自动获取焦点?
解决Blazor Server模态框打开时首个输入框自动获焦问题
你遇到的autofocus无效问题,本质是因为模态框未打开时,BodyTemplate里的输入框要么还没被渲染到DOM中,要么处于隐藏状态——autofocus属性仅在元素首次插入可见DOM时才会触发自动聚焦,所以直接加属性没用。下面给两种可行的解决方案:
方案一:通过ElementReference+JS互操作手动设置焦点
这种方法直接获取第一个输入框的引用,在模态框完全显示后调用JS聚焦:
- 在组件中注入
IJSRuntime,给第一个输入框添加@ref引用:
@inject IJSRuntime JS <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; @if (count == 0) { <!-- 给第一个输入框添加ElementReference --> <input @bind="@MulipleSerialNumbers[count]" @ref="firstSerialInput" class="col-4 m-1" /> } else { <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> </Modal>
- 在代码块中处理模态框打开逻辑,显示后触发聚焦:
@code { private Modal? modalMultipleSerialNumbers; private ElementReference firstSerialInput; private string[] MulipleSerialNumbers = new string[SD.MaxNumberOfMultiples]; // 打开模态框的方法(根据你的实际调用逻辑调整) public async Task OpenMultiSerialModal() { // 先显示模态框 await modalMultipleSerialNumbers!.ShowAsync(); // 等待模态框DOM渲染完成(短延迟确保元素已存在) await Task.Delay(10); // 调用JS函数聚焦 await JS.InvokeVoidAsync("focusElement", firstSerialInput); } private void OnClearModalClick() { // 你的清空逻辑 Array.Clear(MulipleSerialNumbers, 0, MulipleSerialNumbers.Length); StateHasChanged(); } private void OnSaveModalClick() { // 你的保存逻辑 modalMultipleSerialNumbers!.CloseAsync(); } }
- 在
wwwroot/index.html的<body>末尾添加JS函数:
<script> function focusElement(element) { element.focus(); } </script>
方案二:监听模态框显示事件(适配Bootstrap类模态框)
如果你的模态框组件基于Bootstrap,可以通过监听shown.bs.modal事件(模态框完全显示后触发)来自动聚焦:
- 给模态框添加唯一
Id,并实现IAsyncDisposable用于清理JS资源:
@inject IJSRuntime JS @implements IAsyncDisposable <Modal @ref="modalMultipleSerialNumbers" Id="multiSerialModal" Title="Add/Change Multiple Serial Numbers" UseStaticBackdrop="true" Size="ModalSize.ExtraLarge"> <!-- 输入框和按钮代码同之前 --> </Modal>
- 在代码块中导入JS模块并设置事件监听:
@code { private Modal? modalMultipleSerialNumbers; private string[] MulipleSerialNumbers = new string[SD.MaxNumberOfMultiples]; private IJSObjectReference? jsModule; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { // 导入自定义JS模块 jsModule = await JS.InvokeAsync<IJSObjectReference>("import", "./scripts/modal-focus.js"); // 传入模态框ID设置监听 await jsModule.InvokeVoidAsync("setupModalAutoFocus", "multiSerialModal"); } } // 清理JS模块资源 async ValueTask IAsyncDisposable.DisposeAsync() { if (jsModule is not null) { await jsModule.DisposeAsync(); } } // 其他方法同上... }
- 在
wwwroot/scripts/下新建modal-focus.js文件:
export function setupModalAutoFocus(modalId) { const modal = document.getElementById(modalId); // 监听模态框完全显示事件 modal.addEventListener('shown.bs.modal', function () { // 找到模态框内第一个输入框并聚焦 const firstInput = this.querySelector('input:first-of-type'); if (firstInput) { firstInput.focus(); } }); }
两种方案都能解决你的问题,方案一更直接,方案二更贴合Bootstrap模态框的原生行为,根据你的组件实际情况选择即可。
内容的提问来源于stack exchange,提问作者Steve Cross
相关产品推荐
相关产品推荐

