Gereksinimler ve Ön Hazırlık
Başarılı bir uygulama geliştirme süreci için geliştirme ortamınızın güncel olması şarttır. 2026 standartlarına uygun bir Flutter projesi için aşağıdaki araçların yüklü olduğundan emin olun:
- Flutter SDK 3.24 veya üzeri bir sürüm.
- Dart 3.5 ve üzeri (Null Safety desteği zorunludur).
- VS Code veya Android Studio gibi, Flutter eklentileri kurulu bir IDE.
- Temel düzeyde State Management (Provider veya Riverpod) bilgisi.
Projenizi oluşturmak için terminalde flutter create dynamic_form_app komutunu çalıştırarak başlayabilirsiniz. Bağımlılık yönetimi için pubspec.yaml dosyanıza herhangi bir harici paket eklemeden, Flutter'ın yerleşik Form widget'ı ile ilerleyeceğiz.
Flutter Form Yapısının Temelleri
Flutter'da form yönetimi Form, GlobalKey ve TextFormField üçlüsü üzerine kuruludur. Form widget'ı, altındaki tüm FormField widget'larını bir çatı altında toplar ve toplu doğrulama (validation) veya sıfırlama (reset) işlemleri yapmanıza olanak tanır.
Aşağıdaki kod örneği, temel bir form iskeletinin nasıl kurulacağını göstermektedir:
final _formKey = GlobalKey();
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Bu alan boş bırakılamaz';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
print("Form başarıyla doğrulandı!");
}
},
child: Text('Gönder'),
),
],
),
)
Burada _formKey, formun durumunu kontrol etmemizi sağlayan bir anahtardır. validate() metodu çağrıldığında, form içindeki tüm validator fonksiyonları tetiklenir ve hata mesajları ekrana yansıtılır.
Dinamik Doğrulama Kuralları Oluşturma
Dinamik formlarda doğrulama kuralları sabit değildir; kullanıcının seçimine veya uygulamanın o anki durumuna göre değişebilir. Örneğin, bir "Diğer" seçeneği seçildiğinde yeni bir metin kutusunun zorunlu hale gelmesi gibi senaryoları yönetmek için validator fonksiyonlarını dinamik olarak tanımlamalıyız.
Aşağıdaki örnekte, bir değişkenin durumuna göre doğrulama kuralının nasıl değiştiğini görebilirsiniz:
bool isOtherSelected = false;
TextFormField(
validator: (value) {
if (isOtherSelected && (value == null || value.isEmpty)) {
return 'Lütfen detay giriniz';
}
return null;
},
)
Bu yaklaşımda, isOtherSelected değişkeni değiştiğinde setState çağrısı yaparak formun yeniden render edilmesini ve validator'ın güncel kuralı kullanmasını sağlarız.
Dinamik Alan Ekleme ve Kaldırma
Kullanıcının form üzerinde yeni alanlar eklemesine izin vermek, dinamik formların en yaygın kullanım alanıdır. Bunun için bir List yapısı kullanarak form alanlarını yönetebiliriz.
List _controllers = [];
void _addField() {
setState(() {
_controllers.add(TextEditingController());
});
}
// ListView.builder içerisinde alanları render edin
ListView.builder(
itemCount: _controllers.length,
itemBuilder: (context, index) {
return TextFormField(
controller: _controllers[index],
validator: (val) => val!.isEmpty ? 'Boş olamaz' : null,
);
},
)
Bu yöntemle, kullanıcı "Yeni Ekle" butonuna bastığında formun yapısını anlık olarak değiştirebilirsiniz. TextEditingController kullanımı, veriye daha sonra kolayca erişebilmemizi sağlar.
Form Doğrulama Yöntemlerinin Karşılaştırılması
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Yerleşik Validator | Hızlı ve basit kurulum | Karmaşık mantıklarda kod tekrarı |
| Controller Tabanlı | Veriye anlık erişim | Form state yönetimi zorlaşabilir |
| Form Builder Paketi | Çok karmaşık formlar için ideal | Ek bağımlılık yükü |
Güvenlik ve Hata Yönetimi
Kritik Uyarı: İstemci tarafındaki (Client-side) doğrulama, kullanıcı deneyimi içindir. Asla sunucu tarafındaki (Server-side) doğrulamayı atlamayın. Kullanıcı, istemci kodunu manipüle edebilir; bu nedenle veritabanına giren her veri sunucuda tekrar kontrol edilmelidir.
Formlarda XSS (Cross-Site Scripting) riskini önlemek için kullanıcıdan alınan verileri doğrudan HTML veya benzeri bir yapıda render etmeyin. Ayrıca, şifre veya kişisel veri gibi hassas bilgileri işlerken obscureText: true özelliğini mutlaka kullanın.
Sıkça Sorulan Sorular
Form doğrulama mesajlarını özelleştirebilir miyim?
Evet, validator fonksiyonu içerisinde istediğiniz string değerini döndürerek hata mesajlarını tamamen özelleştirebilirsiniz.
Formu nasıl tek seferde sıfırlayabilirim?
_formKey.currentState!.reset() metodu ile formdaki tüm alanları başlangıç değerlerine döndürebilirsiniz.
Dinamik formlarda performans kaybı yaşanır mı?
Çok sayıda alan varsa ListView.builder kullanarak sadece ekranda görünen widget'ların oluşturulmasını sağlayarak performansı optimize edebilirsiniz.
Validator fonksiyonu neden çalışmıyor?
TextFormField widget'ınızın bir Form widget'ı içinde olduğundan ve _formKey ile ilişkilendirildiğinden emin olun.
Asenkron doğrulama (API kontrolü) nasıl yapılır?
Validator fonksiyonları senkron çalışır. API kontrolü için form gönderilmeden önce bir "loading" state'i oluşturup, gönderim butonuna basıldığında asenkron bir doğrulama süreci başlatmalısınız.
İleri Seviye Form Yönetimi: FormBuilder ve Reactive Yaklaşım
Dinamik formlar büyüdükçe, standart TextFormField ve GlobalKey yönetimi karmaşıklaşabilir. Profesyonel projelerde, formun durumunu (state) daha merkezi bir noktadan yönetmek için Reactive Forms yaklaşımı tercih edilir. Bu yöntem, form verilerini bir model gibi ele almanızı sağlar ve formun her bir alanını birer FormControl olarak tanımlar.
Aşağıdaki örnekte, reactive_forms kütüphanesinin temel mantığını kullanarak, formun durumunu nasıl daha temiz bir şekilde yönetebileceğinizi görebilirsiniz:
// Reactive form tanımı
final form = FormGroup({
'email': FormControl(validators: [Validators.required, Validators.email]),
'age': FormControl(validators: [Validators.number, Validators.min(18)]),
});
// Widget içerisinde kullanımı
ReactiveForm(
formGroup: form,
child: Column(
children: [
ReactiveTextField(
formControlName: 'email',
decoration: InputDecoration(labelText: 'E-posta'),
),
ReactiveTextField(
formControlName: 'age',
decoration: InputDecoration(labelText: 'Yaş'),
),
],
),
);
Dinamik Formlarda Performans Optimizasyonu
Dinamik formlar, özellikle çok sayıda alan (input) içerdiğinde, her tuş vuruşunda tüm ağacın yeniden oluşturulmasına (rebuild) neden olabilir. Performans kaybını önlemek için const yapıları kullanmak ve StatefulWidget içerisinde setState kullanımını minimize etmek kritik öneme sahiptir.
Performansı Artırmak İçin İpuçları:
- ValueListenableBuilder Kullanımı: Formun tamamını değil, sadece değişen alanı dinlemek için
ValueListenableBuilderveyaStreamBuildertercih edin. - FocusNode Yönetimi: Dinamik alanlarda
FocusNodenesnelerini manuel yöneterek, klavye açılıp kapanırken gereksiz rebuild'lerin önüne geçin. - Debounce Uygulaması: Özellikle API üzerinden yapılan asenkron doğrulamalarda, kullanıcı yazmayı bitirene kadar beklemek için
debounce(gecikmeli işlem) mekanizması kurun.
Aşağıdaki kod bloğu, bir metin girişinde 500ms'lik bir debounce uygulayarak API isteklerini nasıl sınırlandırabileceğinizi gösterir:
import 'dart:async';
Timer? _debounce;
void onSearchChanged(String query) {
if (_debounce?.isActive ?? false) _debounce!.cancel();
_debounce = Timer(const Duration(milliseconds: 500), () {
// API doğrulama işlemini burada tetikleyin
validateFieldWithApi(query);
});
}
Birim Testleri ile Form Doğrulama Süreci
Form doğrulama mantığınızın hatasız çalıştığından emin olmak için birim testleri (unit tests) yazmak, özellikle karmaşık doğrulama kurallarında hayat kurtarır. Flutter'da flutter_test kütüphanesini kullanarak formun geçerlilik durumunu test edebilirsiniz.
test('Email alanı geçersiz formatta hata vermeli', () {
final emailControl = FormControl(
value: 'hatali-email',
validators: [Validators.email]
);
expect(emailControl.valid, isFalse);
expect(emailControl.hasError('email'), isTrue);
});
Bu yaklaşım, formunuzun kullanıcı arayüzünden bağımsız olarak mantıksal doğruluğunu garanti altına almanızı sağlar ve gelecekte yapacağınız değişikliklerde formun bozulmadığından emin olmanıza yardımcı olur.
Sonuç
Flutter ile dinamik form doğrulama sistemi kurmak, doğru mimari ile oldukça esnek ve güçlü bir yapıya dönüşebilir. Bu rehberde, temel form yapısından başlayarak, dinamik alan yönetimi ve güvenlik prensiplerine kadar geniş bir yelpazeyi ele aldık. Bir sonraki adım olarak, form verilerini bir model sınıfına (JSON serialization) dönüştüren ve API ile haberleşen bir yapı kurmayı deneyebilirsiniz.
Kod güvenliği sorumluluk reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanılacak uygulamalarda, girdi temizleme (input sanitization) ve sunucu tarafı doğrulama prosedürlerini mutlaka uygulayın.


Yorumlar (0)
Yorum Yaz