Bootstrap Modal ile SweetAlert2 Input Focus Sorunu ve Çözümü
Bootstrap Modal açıkken SweetAlert2 input'larına yazılamaması sorununu ve bunun teknik nedenleriyle çözüm yolunu detaylıca inceliyoruz.
Bootstrap modal kullanırken, aynı anda SweetAlert2 ile bir input penceresi açmak istiyorsanız dikkat! Özellikle modal hala açıkken bir <input>
alanı içeren SweetAlert penceresi açtığınızda, input alanına yazı yazılamadığını fark etmiş olabilirsiniz.
Bu yazıda bu sorun neden olur, nasıl anlaşılır ve nasıl çözülür, teknik detaylarıyla anlatacağım.
🎯 Problem Tanımı
Aşağıdaki gibi bir senaryoda:
1
2
3
4
5
6
// Bootstrap Modal açıkken çalışıyor
Swal.fire({
title: 'Bir şey yaz',
input: 'text',
...
});
Input’a yazı yazamazsınız. Klavyeden hiçbir karakter girilemez. Çünkü Bootstrap modal’ın “focus trap” (odak tuzağı) devrede kalmaya devam eder ve dışarıdaki hiçbir odaklanma olayına izin vermez.
Teknik Sebep
Bootstrap Modal (v5+), açıldığında tüm sayfa odaklarını içerideki modal’a kilitleyen bir sistem kullanır. Bu sistem FocusTrap
denen bir yapı ile modal dışına yapılan focusin
olaylarını engeller.
SweetAlert2, kendi penceresini body’nin sonuna (<body>
tag’ı dışına) ekler. Ancak Bootstrap modal hala açık olduğundan, bu alert’in içindeki <input>
gibi alanlara yapılan odaklama Bootstrap tarafından engellenir.
Bu çakışma, özellikle SweetAlert2’nin input’lu prompt’larında belirgin hale gelir.
Çözüm
SweetAlert2 açıldığında, onun .swal2-container
elemanını, Bootstrap modal’ın içine alırsak, focus çakışması ortadan kalkar. Böylece SweetAlert bileşeni de modal içinde “güvenli” bir alan olarak kabul edilir.
Aşağıdaki çözüm bunu yapar:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Bootstrap 5.1.x environment.
// Sweat Alert 2@11
Swal.fire({
title: 'İsminizi girin',
input: 'text',
didOpen: () => {
// MAGIC - Move SweetAlert2 window to Bootstrap modal body
const swalContainer = document.querySelector('.swal2-container');
const modalBody = document.querySelector('.modal-body');
if (swalContainer && modalBody) {
modalBody.appendChild(swalContainer);
}
}
});
Bu didOpen
fonksiyonu sayesinde:
- SweetAlert2’nin root elementi
.swal2-container
, Bootstrap modal’ın içindeki.modal-body
içerisine taşınır. - Bootstrap artık bu alert’i kendi modal alanı olarak görür.
- Böylece input alanı odaklanabilir ve kullanıcı rahatça veri girişi yapabilir.
Bonus: Neden focus: false
veya focustrap.deactivate()
işe yaramaz?
new bootstrap.Modal(..., { focus: false })
veya modal._focustrap.deactivate()
kullanmak teorik olarak işe yarayabilir. Ancak bu ayarlar:
- Modal daha önce JS ile başlatılmadıysa uygulanamaz.
- Framework üzerinden init edilmişse
getInstance
çalışmaz. - Özellikle Vue/React/CoreUI gibi yapılar bu
bootstrap.Modal
örneğine ulaşmayı engelleyebilir.
Bu nedenle, SweetAlert’in kendisini modal içine taşımak, her senaryoda çalışan, evrensel bir çözümdür.
Bulunmuş Farklı Çözümler
İnternette araştırdığımızda farklı çözüm önerileri de geliyor. Tabii bunlar da işe yarıyor olabilir, sonuçta herkes aynı versiyonları kullanmıyor. Versiyon farklılıklarıda bize farklı çözümler bulmamızı gerektiriyor. İşte derlediğim bazı çözüm olmuş yöntemler:
1
2
3
// Bootstrap 5.1.x environment.
$(document).off('focusin'); //NG
$(document).off('focusin.bs.focustrap'); //NG
1
2
3
4
// Bootstrap 5.1.x environment.
$('#myModal').on('shown.bs.modal', function() {
$(document).off('focusin.modal');
});
1
2
3
4
<!-- Add data-bs-focus="false" to the modal html. -->
<div class="modal fade" id="dialog_box" data-bs-focus="false" aria-hidden="true" tabindex="-1">
...
</div>
Bootstrap Modal açıkken SweetAlert2 ile input kullanmak istiyorsanız:
- Ya modal focus tuzağını manuel devre dışı bırakın (zor).
- Ya da daha temiz bir şekilde SweetAlert2’yi modal içine taşıyın (kolay ve sağlam).
SweetAlert2’nin .swal2-container
elemanını .modal-body
içine eklemek, tüm focus sorunlarını çözen pratik bir yöntemdir.