Bootstrap 5模态框Tab切换时聚焦Datepicker但不弹出面板
问题
使用Bootstrap 5开发页面,模态框内包含3个Tab标签页,其中GPSMAP_day Tab内的日期输入框绑定了jQuery UI Datepicker。需求是切换到该Tab时,日期输入框自动获得焦点,但Datepicker的选择面板不会弹出。
之前尝试调用$('#day-dateInput').datepicker("hide")来隐藏面板,但会出现面板闪关的视觉问题,体验不佳。
解决方案
以下几种方法可以从根源上阻止Datepicker在Tab切换聚焦时弹出,避免闪关问题:
方法1:通过beforeShow事件控制弹出时机
给Datepicker添加beforeShow回调,判断当前聚焦是否由Tab切换触发,若是则返回false阻止面板弹出:
$('#day-dateInput').datepicker({ dateFormat: 'dd-mm-yy', autoclose: true, todayHighlight: true, maxDate: today, beforeShow: function(input, inst) { // 判断是否是Tab切换触发的聚焦 const isTabTriggered = inst.input.data('tabTriggeredFocus'); if (isTabTriggered) { inst.input.data('tabTriggeredFocus', false); return false; } return true; } }); // Tab切换时标记聚焦来源 $('#day-tab').on('shown.bs.tab', function () { $('#day-dateInput').data('tabTriggeredFocus', true).focus(); });
方法2:临时禁用Datepicker,聚焦后恢复
在Tab切换时先销毁Datepicker避免弹出,聚焦完成后重新初始化:
let datepickerConfig = { dateFormat: 'dd-mm-yy', autoclose: true, todayHighlight: true, maxDate: today }; $('#day-dateInput').datepicker(datepickerConfig); $('#day-tab').on('shown.bs.tab', function () { // 销毁Datepicker阻止弹出 $('#day-dateInput').datepicker('destroy'); // 聚焦输入框 $('#day-dateInput').focus(); // 延迟重新初始化Datepicker setTimeout(() => { $('#day-dateInput').datepicker(datepickerConfig); }, 100); });
方法3:监听focusin事件阻止弹出
通过标记状态,在Tab触发的聚焦时临时禁用Datepicker:
let isTabFocus = false; $('#day-tab').on('shown.bs.tab', function () { isTabFocus = true; $('#day-dateInput').focus(); }); $('#day-dateInput').on('focusin', function() { if (isTabFocus) { $(this).datepicker('disable'); setTimeout(() => { $(this).datepicker('enable'); isTabFocus = false; }, 50); } });
完整修改后的示例代码
<!DOCTYPE html> <html lang="en"> <head> <title>GPS</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.14.1/themes/base/jquery-ui.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.14.1/themes/base/theme.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.14.1/jquery-ui.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script> <script language="JavaScript"> function showModal() { const modal = new bootstrap.Modal(document.getElementById('empInfoModal')); modal.show(); } $(document).ready(function() { //set datepickers var today = new Date(); $('#day-dateInput').datepicker({ dateFormat: 'dd-mm-yy', autoclose: true, todayHighlight: true, maxDate: today, beforeShow: function(input, inst) { const isTabTriggered = inst.input.data('tabTriggeredFocus'); if (isTabTriggered) { inst.input.data('tabTriggeredFocus', false); return false; } return true; } }); // Set default date to today $('#day-dateInput').datepicker('setDate', today); // Focus on the date input when the tab is shown $('#day-tab').on('shown.bs.tab', function () { $('#day-dateInput').data('tabTriggeredFocus', true).focus(); }); }); </script> </head> <body> <div class="container-fluid mt-2"> <div class="card"> <div class="card-header"> <div class="row mt-2"> <div class="col-2 h4"> </div> <div class="col-8 h2 text-center"> <span class="font-weight-bold"><i class="fa fa-car"> </i>header</span> </div> <div class="col-2 text-end"> </div> </div> </div> <div class="card-body" id="mapContainer"> <!-- Sidebar --> <div class="sidebar" id="sidebar"> <button class="btn btn-danger" id="modalShow" onclick="showModal()">show modal</button> </div> <!-- Map Container --> <div class="map-container" id="map"></div> </div> </div> </div> <!-- Modal start - employee info --> <div class="modal fade" id="empInfoModal" tabindex="-1" aria-labelledby="empInfoModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="empInfoModalLabel">GPSMAP_info</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <input class="d-none" type="text" id="empInfoModal-deviceId"> <!-- Tabs Navigation --> <ul class="nav nav-tabs" id="infoTabs" role="tablist"> <li class="nav-item" role="presentation"> <button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">GPSMAP_info</button> </li> <li class="nav-item" role="presentation"> <button class="nav-link" id="day-tab" data-bs-toggle="tab" data-bs-target="#day" type="button" role="tab" aria-controls="day" aria-selected="false">GPSMAP_day</button> </li> <li class="nav-item" role="presentation"> <button class="nav-link" id="period-tab" data-bs-toggle="tab" data-bs-target="#period" type="button" role="tab" aria-controls="period" aria-selected="false">GPSMAP_period</button> </li> </ul> <!-- Tabs Info Content --> <div class="tab-content" id="infoTabContent"> <div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab"> <p>home content</p> </div> <!-- Tabs Day Content --> <div class="tab-pane fade" id="day" role="tabpanel" aria-labelledby="day-tab"> <div class="row mt-3"> <div class="col-2"> <label for="day-dateInput" class="col-form-label">select date</label> </div> <div class="col-3"> <input type="text" class="form-control" id="day-dateInput"> </div> <div class="col-2"> </div> </div> </div> <!-- Tabs Period Content --> <div class="tab-pane fade" id="period" role="tabpanel" aria-labelledby="period-tab"> <p>periode content</p> </div> </div> </div> </div> </div> </div> </body> </html>
内容的提问来源于stack exchange,提问作者Anja R
相关产品推荐
相关产品推荐

