Bootstrap 5.0'da form doğrulaması tarayıcının yerleşik kısıt denetimine dayanır: alanlara required gibi HTML öznitelikleri yazarsınız, Bootstrap da geçersiz alanları kırmızı, geçerli alanları yeşil kenarlık ve simgeyle gösterir. Bu stiller formda .was-validated sınıfı varken :invalid ve :valid durumlarına göre devreye girer; sunucu tarafında karar verdiğinizde aynı görünümü .is-invalid ve .is-valid sınıflarıyla elle verirsiniz. Mesajlar .invalid-feedback ve .valid-feedback öğelerine yazılır.

Bu yazıda üç yolu karşılaştırıyoruz: Bootstrap'in özel stilleri ve küçük bir JavaScript parçası, tarayıcının varsayılan mesajları ve sunucu tarafı sınıflar. Ardından desteklenen öğeleri, tooltip biçimli mesajları, Sass ile özelleştirmeyi ve en sık hataları ele alıyoruz. required, pattern, minlength gibi özniteliklerin nasıl çalıştığı HTML'in konusudur ve HTML form doğrulama rehberinde anlatılıyor. Anlatım Bootstrap 5.0 belgelerine ve v5.0.2 kaynak koduna dayanır; sonraki 5.x sürümleri yeni özellikler ekledi, güncel sürüm için getbootstrap.com'a bakın.

Doğrulama nasıl çalışır?

Doğrulama nasıl çalışır? HTML doğrulaması CSS'in :invalid ve :valid sözde sınıflarıyla yansıtılır ve..., Bootstrap bu stilleri .was-validated sınıfına sahip bir üst öğenin...
  • HTML doğrulaması CSS'in :invalid ve :valid sözde sınıflarıyla yansıtılır ve <input>, <select>, <textarea> öğelerine uygulanır.
  • Bootstrap bu stilleri .was-validated sınıfına sahip bir üst öğenin, genellikle <form> öğesinin altına sınırlar. Böyle olmasaydı zorunlu ama boş her alan sayfa açılır açılmaz geçersiz görünürdü.
  • Formun görünümünü sıfırlamak için, örneğin AJAX ile gönderimden sonra, .was-validated sınıfını formdan yeniden kaldırırsınız.
  • Sunucu tarafı doğrulama için yedek olarak .is-invalid ve .is-valid sınıfları vardır; bunlar .was-validated üst öğesi gerektirmez.
  • CSS'in çalışma biçimi yüzünden DOM'da alandan önce gelen bir <label> özel JavaScript olmadan biçimlendirilemez.
  • Modern tarayıcılar, alanları JavaScript ile denetlemeye yarayan kısıt doğrulama API'sini (constraint validation API) destekler; özel hata metni için setCustomValidity kullanılabilir.

Bu maddelerden en çok gözden kaçanı dördüncüsüyle beşincisinin birleşimi. Bootstrap'in mesajları gösterme yöntemi CSS'in kardeş seçicisine dayanır. Bootstrap 5.0.2 derlenmiş CSS dosyasında bu kural şöyle tanımlıdır:

css
.invalid-feedback {
  display: none;
  width: 100%;
  margin-top: 0.25rem;
  font-size: 0.875em;
  color: #dc3545;
}
/* (kısaltıldı) */
.was-validated :invalid ~ .invalid-feedback,
.was-validated :invalid ~ .invalid-tooltip,
.is-invalid ~ .invalid-feedback,
.is-invalid ~ .invalid-tooltip {
  display: block;
}

Mesaj öğesi normalde gizlidir. Görünmesi için aynı üst öğe içinde, geçersiz alandan sonra gelen bir kardeş olması gerekir. Mesajı alanın üstüne koyarsanız ya da alanı ayrı bir <div> içine alıp mesajı dışarıda bırakırsanız kural eşleşmez ve mesaj hiç görünmez. Aynı mantıkla alan kenarlığı #dc3545 kırmızısına, geçerli durumda #198754 yeşiline döner, sağ tarafa bir SVG simgesi eklenir ve odak halkası da durum rengini alır.

Özel stiller: novalidate ve başlangıç kodu

Bootstrap'in kendi mesajlarını kullanmak için forma novalidate boole özniteliğini eklersiniz. Bu öznitelik tarayıcının varsayılan uyarı balonlarını kapatır ama JavaScript'teki doğrulama API'lerine erişimi korur. Belgelerdeki örnek forma ayrıca kendi seçtikleri .needs-validation sınıfını verir; bu bir CSS sınıfı değil, aşağıdaki kodun formu bulmak için kullandığı bir işarettir.

html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-6">
    <label for="kayitAd" class="form-label">Ad</label>
    <input type="text" class="form-control" id="kayitAd" required>
    <div class="valid-feedback">Uygun görünüyor.</div>
    <div class="invalid-feedback">Lütfen adınızı yazın.</div>
  </div>
  <div class="col-md-6">
    <label for="kayitKullanici" class="form-label">Kullanıcı adı</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="kayitOnek">@</span>
      <input type="text" class="form-control" id="kayitKullanici" aria-describedby="kayitOnek" required>
      <div class="invalid-feedback">Bir kullanıcı adı seçin.</div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="kayitIl" class="form-label">İl</label>
    <select class="form-select" id="kayitIl" required>
      <option selected disabled value="">Seçin...</option>
      <option>Ankara</option>
      <option>İstanbul</option>
    </select>
    <div class="invalid-feedback">Lütfen bir il seçin.</div>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" value="" id="kayitOnay" required>
      <label class="form-check-label" for="kayitOnay">Kullanım koşullarını kabul ediyorum</label>
      <div class="invalid-feedback">Devam etmek için onaylamalısınız.</div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Kaydol</button>
  </div>
</form>

Formdaki her mesaj, ilgili alanın kardeşi olarak alandan sonra yer alıyor. Giriş grubundaki mesaj grubun içinde ve grup .has-validation sınıfını taşıyor; bu sınıf olmadan mesaj grubun son çocuğu olduğu için alanın sağ köşeleri yanlışlıkla düzleşirdi (input group yazısında ayrıntısı var). Select'in ilk seçeneği value="" ile boş değer taşıyor; required bir select'te boş değer geçersiz sayılır, bu yüzden kullanıcı gerçek bir il seçene kadar alan kırmızı kalır. Checkbox'ın mesajı da .form-check içinde, etiketten sonra duruyor.

Belgeler formla birlikte şu başlangıç kodunu verir. Kod .needs-validation sınıflı her formu bulur, gönderme olayını dinler, form geçersizse gönderimi durdurur ve her durumda forma .was-validated ekler:

javascript
// Belgelerdeki başlangıç kodu (validate-forms.js)
(function () {
  'use strict'

  var forms = document.querySelectorAll('.needs-validation')

  Array.prototype.slice.call(forms)
    .forEach(function (form) {
      form.addEventListener('submit', function (event) {
        if (!form.checkValidity()) {
          event.preventDefault()
          event.stopPropagation()
        }

        form.classList.add('was-validated')
      }, false)
    })
})()

Akış şöyle işler: sayfa açıldığında formda .was-validated olmadığı için hiçbir alan renklenmez. Kullanıcı "Kaydol" butonuna bastığında checkValidity() formdaki tüm kısıtları denetler; bir alan bile geçersizse preventDefault() gönderimi engeller. Sınıf eklendiği anda CSS devreye girer ve tüm alanlar durumlarına göre kırmızı ya da yeşil görünür; kullanıcı yazdıkça :valid ve :invalid canlı olarak değiştiği için renk de anında güncellenir. Bu kod Bootstrap'in JavaScript paketinin parçası değildir, kendi sayfanıza eklersiniz. JavaScript tarafını öğrenmek için JavaScript öğrenme rehberi iyi bir başlangıç. Resmî Checkout şablonu da aynı kodu kullanır.

Tarayıcının varsayılan mesajları

Özel mesaj yazmak ya da JavaScript eklemek istemiyorsanız tarayıcının varsayılan davranışına bırakabilirsiniz. Bunun için formdan novalidate ve .needs-validation işaretini kaldırmanız yeterli; alanlardaki required gibi öznitelikler kalır. Kullanıcı formu eksik göndermeye çalıştığında tarayıcı kendi uyarı balonunu gösterir. Belgelere göre bu balonun görünümü tarayıcıya ve işletim sistemine göre değişir ve CSS ile biçimlendirilemez; ancak metnini JavaScript ile özelleştirebilirsiniz. Belgeler erişilebilirlik açısından da bu yöntemi önerilen iki yoldan biri olarak sayar.

Sunucu tarafı doğrulama: is-invalid ve is-valid

Belgeler istemci tarafı doğrulamayı önerir, ama alan adının alınmış olması gibi kararları ancak sunucu verebilir. Bu durumda sayfayı sunucuda üretirken geçersiz alanlara .is-invalid, geçerli alanlara .is-valid sınıfını eklersiniz. Bu sınıflar .was-validated gerektirmez ve .invalid-feedback mesajlarıyla birlikte çalışır.

html
<form class="row g-3">
  <div class="col-md-6">
    <label for="sunucuEposta" class="form-label">E-posta</label>
    <input type="email" class="form-control is-valid" id="sunucuEposta" value="ayse@ornek.com">
    <div class="valid-feedback">Bu adres kullanılabilir.</div>
  </div>
  <div class="col-md-6">
    <label for="sunucuKullanici" class="form-label">Kullanıcı adı</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="sunucuOnek">@</span>
      <input type="text" class="form-control is-invalid" id="sunucuKullanici" value="ayse" aria-describedby="sunucuOnek sunucuKullaniciHata" required>
      <div id="sunucuKullaniciHata" class="invalid-feedback">Bu kullanıcı adı alınmış.</div>
    </div>
  </div>
</form>

Geçersiz alanlarda belgeler hata mesajını aria-describedby ile alana bağlamanızı ister. Bu öznitelik boşlukla ayrılmış birden fazla id alabilir; örnekte alan hem @ eklentisini hem de hata mesajını gösteriyor. Böylece alan zaten bir yardım metnine bağlıysa o bağ korunur, hata mesajı da eklenir. Sunucu tarafı seçenek, bu yazının başındaki erişilebilirlik uyarısında belgelerin önerdiği iki yoldan biridir.

Aynı sınıflar floating label ile de çalışır: belgelerdeki örnekte .form-floating içindeki bir alana .is-invalid verildiğinde alan kırmızı kenarlık ve uyarı simgesiyle görünür, etiket de yüzen konumunu korur. Mesaj eklemek isterseniz .invalid-feedback öğesini yine alanın sonraki kardeşi olacak şekilde etiketten sonra, aynı sarmalayıcının içine yazın; kardeş seçici aradaki etiketi atlayarak mesaja ulaşır.

Hangi yöntem ne zaman?

Hangi yöntem ne zaman? Bootstrap özel stilleri, Tarayıcı varsayılanı, Sunucu tarafı
YöntemGerekenlerMesaj görünümüNot
Bootstrap özel stillerinovalidate, başlangıç kodu, was-validatedBootstrap renkleri ve simgeleribelgelere göre şu an erişilebilir değil
Tarayıcı varsayılanıyalnızca HTML öznitelikleritarayıcıya göre değişir, biçimlendirilemezbelgelerin önerdiği yollardan biri
Sunucu tarafıis-invalid / is-valid, aria-describedbyBootstrap renkleri ve simgeleribelgelerin önerdiği yollardan biri

Desteklenen öğeler

Belgelere göre doğrulama stilleri şu kontrollerde çalışır: .form-control sınıflı <input> ve <textarea> öğeleri (giriş gruplarında en fazla bir .form-control ile), .form-select sınıflı select'ler ve .form-check yapıları. Derlenmiş CSS'ten birkaç ayrıntı daha çıkar. Durum simgesi select'te yalnızca .form-select ile gösterilir; ok simgesinin yanına ikinci bir arka plan görseli olarak eklenir ve sağ iç boşluk 4.125rem olur. multiple veya size özniteliği olan select'lerde simge eklenmez, v5'teki değişiklik notları da bunu belirtir. Checkbox ve radio'da kutunun kenarlığı ve etiketin rengi durum rengine döner; etiket burada input'tan sonra geldiği için kardeş seçiciyle boyanabilir. Textarea'da simge sağ üst köşeye yerleşir.

Radyo grubunda mesajı yalnızca son radyonun .form-check öğesine koyun. Aynı name değerine sahip zorunlu radyolardan hiçbiri seçili değilse hepsi geçersiz sayılır ve hepsi kırmızıya döner; mesajı her radyoya yazarsanız aynı uyarı alt alta tekrar eder. Belgelerdeki desteklenen öğeler örneği de mesajı yalnızca ikinci radyonun altına koyar.

Tooltip biçimli mesajlar

Form düzeniniz uygunsa .invalid-feedback ve .valid-feedback yerine .invalid-tooltip ve .valid-tooltip kullanabilirsiniz. Derlenmiş CSS'e göre tooltip position: absolute ve top: 100% ile alanın hemen altında, z-index: 5 ile diğer öğelerin üstünde, yarı saydam kırmızı veya yeşil zeminde beyaz yazıyla görünür. Mutlak konumlandırma yüzünden belgeler tooltip'i taşıyan alanın üst öğesinde position: relative bulunmasını şart koşar; örneklerde bu iş için sütunlara .position-relative yardımcı sınıfı eklenir.

html
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-6 position-relative">
    <label for="ipucuSehir" class="form-label">Şehir</label>
    <input type="text" class="form-control" id="ipucuSehir" required>
    <div class="invalid-tooltip">Lütfen bir şehir yazın.</div>
  </div>
  <div class="col-md-6 position-relative">
    <label for="ipucuPosta" class="form-label">Posta kodu</label>
    <input type="text" class="form-control" id="ipucuPosta" required>
    <div class="invalid-tooltip">Geçerli bir posta kodu yazın.</div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Gönder</button>
  </div>
</form>

Tooltip akıştan çıktığı için altındaki öğeyi aşağı itmez, onun üstüne biner. Alanlar arasında yeterli dikey boşluk yoksa mesaj alttaki alanı kapatabilir; bu yüzden tooltip biçimini satırlar arasında boşluk olan düzenlerde tercih edin. Konumlandırma sınıfları position yardımcı sınıfları yazısında.

Sass ile özelleştirme

Doğrulama stilleri _variables.scss içindeki $form-validation-states map'inden üretilir. Map'te varsayılan olarak valid ve invalid durumları vardır; her biri bir color ve bir icon değeri taşır. Renkler $form-feedback-valid-color (varsayılanı $success) ve $form-feedback-invalid-color (varsayılanı $danger) değişkenlerinden gelir. Bir döngü map'teki her durum için form-validation-state mixin'ini çağırır; durum seçicisini üreten form-validation-state-selector mixin'i ise valid ve invalid için hem .was-validated :valid biçimini hem .is-valid sınıfını, başka adlı durumlar için yalnızca .is- önekli sınıfı yazar.

Belgeler bu noktada iki uyarı yapar. Map'e başka durumlar eklemek mümkündür ama tarayıcılar yalnızca geçerli ve geçersiz durumlarını bilir, ek durumları ancak sınıflarla kendiniz verirsiniz. İkincisi, belgeler $form-validation-states değerlerini form-validation-state mixin'ini de değiştirmeden özelleştirmeyi önermez. Simgeleri tamamen kapatmak istiyorsanız Sass seçenekleri yazısında anlatılan $enable-validation-icons değişkenini false yapın; belgelere göre bu seçenek metin alanlarındaki ve bazı özel form öğelerindeki background-image durum simgelerini yönetir. Değişken ezme sırası Sass ile özelleştirme yazısında.

Sık yapılan hatalar

Sık yapılan hatalar: novalidate unutmak, Mesajı alanın kardeşi yapmamak, Sayfa açılırken was-validated yazmak, AJAX sonrası sıfırlamamak
  • novalidate unutmak: Bu öznitelik tarayıcının varsayılan uyarı balonlarını kapatır; yazılmazsa tarayıcının kendi balonları devreye girer ve Bootstrap'in mesajlarını beklediğiniz gibi görmezsiniz.
  • Mesajı alanın kardeşi yapmamak: .invalid-feedback geçersiz alanla aynı üst öğede ve alandan sonra olmalıdır.
  • Sayfa açılırken was-validated yazmak: Kullanıcı hiçbir şey yapmadan tüm zorunlu alanlar kırmızı görünür. Sınıfı gönderim denemesinde ekleyin.
  • AJAX sonrası sıfırlamamak: Form temizlense de .was-validated kalırsa boş alanlar hemen kırmızıya döner; sınıfı kaldırın.
  • Select'te boş değerli seçenek koymamak: Belgelerdeki örneklerde "Seçin..." seçeneği selected disabled value="" taşır; boş değer olmazsa ilk seçenek de geçerli bir seçim sayılabilir. Kuralın HTML tarafı HTML form doğrulama yazısında.
  • Giriş grubunda has-validation unutmak: Mesaj grubun son çocuğu olduğu için köşeler bozulur.
  • Tooltip için konum vermemek: Üst öğede position: relative yoksa tooltip yanlış yerde açılır.
  • Etiketin renklenmesini beklemek: Alandan önce gelen bir .form-label CSS ile boyanamaz; yalnızca form-check etiketleri renk değiştirir.

Sık Sorulan Sorular

Bootstrap 5 doğrulaması JavaScript gerektirir mi?

Özel stiller için evet, belgelerdeki kısa başlangıç kodu gerekir; bu kod Bootstrap'in JS paketinde değildir. Tarayıcı varsayılanları ve sunucu tarafı .is-invalid sınıfları JavaScript olmadan çalışır.

Hata mesajı neden görünmüyor?

En sık nedenler: formda .was-validated yoktur, mesaj alanın sonraki kardeşi değildir ya da alan gerçekten geçerlidir. Sunucu tarafında alana .is-invalid eklemeyi unutmuş olabilirsiniz.

Formu yeniden kullanılabilir hâle nasıl getiririm?

Gönderimden sonra formun classList listesinden was-validated sınıfını kaldırın; sunucu tarafı sınıfları kullandıysanız .is-invalid ve .is-valid sınıflarını da alanlardan silin.

Kırmızı ve yeşil simgeleri nasıl kaldırırım?

Sass ile derliyorsanız $enable-validation-icons değişkenini false yapın; kenarlık ve mesaj renkleri kalır, yalnızca alanların içindeki durum simgeleri üretilmez. Derlenmiş CSS dosyasını olduğu gibi kullanıyorsanız bu seçenek yoktur; simgeler background-image ile çizildiği için kendi CSS'inizle ezmeniz gerekir.

Özel hata metnini nasıl veririm?

Bootstrap mesajlarında metni doğrudan .invalid-feedback öğesine yazarsınız. Tarayıcı balonlarının metni için belgeler setCustomValidity yöntemini hatırlatır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Bootstrap öğrenme rehberi · HTML form doğrulama · Form control · Input group · Erişilebilirlik · JavaScript öğrenme rehberi