e
sv

Flutter'da reaktif formlar oluşturma

avatar

Yazılım Method

  • e 0

    Mutlu

  • e 0

    Eğlenmiş

  • e 0

    Şaşırmış

  • e 0

    Kızgın

  • e 0

    Üzgün

Geliştirdiğiniz hemen hemen her uygulamada, er ya da geç kullanıcı girdisini yakalama ihtiyacı ortaya çıkacaktır. Neyse ki, metin girişlerini yakalamak Flutter'da oldukça basittir. Ancak, bir forma daha fazla alan ve girdi türü eklendikçe, bu bilgileri yakalamanın karmaşıklığı hızla artar.

Normal olarak, metin alanları, tarih alanları veya diğer herhangi bir girdi türü olsun, bu girdi alanlarına "kontroller" denir. Doğrulama da bir sorun haline gelebilir, çünkü belirli alanlar için basit doğrulama bile uzun özel doğrulayıcıların yazılmasını gerektirebilir.

Bu yazıda, giriş doğrulama ve diğer alanların değerine göre değişen alanlar içeren bir kayıt formu oluşturacağız. Bunu önce reaktif formlar kullanmadan gerçekleştireceğiz, ardından Flutter'da reaktif formların faydalarını anlamak için aynı formu reaktif formlar kullanarak yeniden uygulayacağız.

Neleri ele alacağız:

Flutter reaktif formlar projesine genel bakış

Yaratacağımız uygulama, insanların tatile gittiklerinde evcil hayvanlarını bırakabilecekleri bir "evcil hayvan oteline" evcil hayvanlar için bir kayıt uygulamasıdır.

Bu uygulamanın çalışması için kişilerin adları ve telefon numaraları, ne tür bir evcil hayvana sahip oldukları ve evcil hayvanlarının beğenileri ve beğenileri gibi ayrıntıları vermeleri gerekiyor. Nihai sonuç şöyle görünecek:

Pet Hotel Uygulamasına Giren ve Flutter Reaktif Formda Bilgi Giren Kullanıcı Gösterildi

Bu formun birkaç şartı vardır.

İlk olarak, kullanıcının seçtiği evcil hayvan türüne bağlı olarak üç takip sorusu değişmelidir.

Ardından, bu üç sorunun yanıtları gereklidir, bu nedenle doldurulduklarından emin olmak için Flutter form doğrulama mantığını eklemeliyiz.

Son olarak, telefon numarası yalnızca rakamlardan oluşmalıdır, bu nedenle sayısal olmayan değerler içeriyorsa, form bu girişi reddetmeli ve kullanıcıyı bilgilendirmelidir.

Formu Flutter'da reaktif formlar olmadan yapma

Bu ilk yaklaşımda, formları kendimiz manuel olarak oluşturuyoruz ve ayrıca bu bireysel alanlardaki metin girişlerini de yakalamak istiyoruz.

Bu nedenle, TextFormField widget'larıyla ilişkilendirebileceğimiz ayrı TextControllers oluşturmaktan sorumluyuz. Seçilen evcil hayvanı barındıracak bir değişken oluşturmaktan da sorumluyuz.

Şimdi bu değişkenleri oluşturalım:

 final _formKey = GlobalKey<FormState>();
Evcil Hayvan Türü? _petType;
son ad = TextEditingController();
final lastName = TextEditingController();
son soruResponses = List.generate(3, (index) => TextEditingController());

Bu alanlara metin yazmak için TextFormField widget'larını oluşturacağız ve bunları uygun denetleyicilere bağlayacağız:

 MetinFormAlan(
  dekorasyon: InputDecoration(hintText: 'First Name'),
  denetleyici: ad,
),
MetinFormAlan(
  dekorasyon: InputDecoration(hintText: 'Soyadı'),
  denetleyici: soyadı,
),

Telefon numarası giriş alanı biraz farklıdır, çünkü hem içinde geçerli bir telefon numarası olduğunu doğrulamamız hem de geçersiz giriş algılandığında kullanıcıyı uyarmamız gerekir:

 MetinFormAlan(
  dekorasyon: InputDecoration(hintText: 'Telefon numarası'),
  autovalidateMode: AutovalidateMode.always,
  doğrulayıcı: (val) {
    if (val == null || val == "") {
      return 'Lütfen bir telefon numarası girin';
    }
    if (int.tryParse(val) == boş) {
      return 'Telefon numarası alanına yalnızca sayıları girin';
    }
    null döndür;
  },
),

Ardından, evcil hayvan seçiciyi belirliyoruz. Bu, kullanıcının ne tür bir evcil hayvan getireceğini seçmesine izin veren bir RadioListTile : Kedi, Köpek veya Echidna.

Kullanıcı bir evcil hayvan türü seçtiğinde, bu sorulara verilen önceki yanıtları da yinelemek ve aynı anda yalnızca bir seçeneğin seçilmesi için bunları temizlemek istiyoruz.

 RadioListTile<PetType>(
  değer: PetType.cat,
  grupDeğeri: _petType,
  onChanged: (val) => setState(() {
    for (soru yanıtlarında son kontrolör) {
      denetleyici.clear();
    }
    _petType = val;
  }),
  başlık: Metin('Kedi'),
),

Son olarak, hangi tür evcil hayvanın seçildiğine bağlı olarak sorduğumuz soruları değiştirmek istiyoruz.

Belirli bir değişkenin değerine bağlı olarak widget ağacını güncelleyecek bir Builder kullanarak başarabiliriz. Bu nedenle, seçilen hayvan türü "Kedi" ise, form o hayvan türü için soruları görüntüler ve aynısı Köpek veya Echidna türü hayvanlar için de geçerlidir.

 inşaatçı(
  oluşturucu: (bağlam) {
    geçiş (_petType) {
      vaka PetType.cat:
        dönüş Sütunu(
          çocuklar: [
            Text("Aa, bu bir kedi!"),
            PetQuestionField(soru: 'Kediyi okşayabilir miyiz?', denetleyici: soruResponses[0]),
            PetQuestionField(soru: 'Üzerine küçük bir kıyafet koyabilir miyiz?', controller: QuestionResponses[1]),
            PetQuestionField(soru: 'Kutulara atlamayı sever mi?', denetleyici: soruResponses[2]),
          ],
        );

      vaka PetType.dog:
        dönüş Sütunu(
          çocuklar: [
            Text("Vay canına! Ayrıntıları nedir?"),
            PetQuestionField(soru: 'Köpeğinizi yıkayabilir miyiz?', denetleyici: soruResponses[0]),
            PetQuestionField(soru: 'Köpeğinizin en sevdiği ikram nedir?', denetleyici: soruResponses[1]),
            PetQuestionField(soru: 'Köpeğiniz diğer köpeklerle uyumlu mu?', denetleyici: soruResponses[2]),
          ],
        );

      vaka PetType.echidna:
        dönüş Sütunu(
          çocuklar: [
            Text("Bu küçük bir dikenli boi. Bize biraz ayrıntı verebilir misin?"),
            PetQuestionField(soru: 'Echidna ne kadar sivri?', denetleyici: soruResponses[0]),
            PetQuestionField(soru: 'Echidna'ya bir hikaye okuyabilir miyiz?', controller: QuestionResponses[1]),
            PetQuestionField(soru: 'Yapraklı yeşillikleri sever mi?', denetleyici: soruResponses[2]),
          ],
        );
      durum boş:
        {
          return Text('Lütfen evcil hayvanınızın türünü yukarıdan seçin');
        }
    }
  },
),

Oluşturulan bireysel form kontrolleriyle, kullanıcının evcil hayvanını kaydetmesi için bir düğme oluşturmanın zamanı geldi. Bu düğme, yalnızca sağlanan girişler geçerliyse kullanıcının devam etmesine izin vermeli ve kullanıcıdan doğrulanamayan girişleri düzeltmesini istemelidir.

 YükseltilmişDüğme(
    onPressed: () {
      // Form kontrolleri şunu bildiriyorsa form geçerlidir. 
      // geçerliler ve bir evcil hayvan türü belirtildi.
      son geçerli = (_formKey.currentState?.validate() ?? false) && _petType != null;
      if (!geçerli) {
      // Geçerli değilse, kullanıcıdan formu düzeltmesini isteyin
        gösterDiyalog(
            bağlam: bağlam,
            oluşturucu: (bağlam) => SimpleDialog(
                  içerik Doldurma: EdgeInsets.all(20),
                  başlık: Metin('Lütfen formu kontrol edin'),
                  çocuklar: [Metin('Bazı ayrıntılar eksik veya yanlış. Lütfen ayrıntıları kontrol edip tekrar deneyin.')],
                ));
      } başka {
      // Geçerliyse alınan değerleri göster
        gösterDiyalog(
          bağlam: bağlam,
          oluşturucu: (bağlam) => SimpleDialog(
            içerik Doldurma: EdgeInsets.all(20),
            başlık: Metin("Her şey bitti!"),
            çocuklar: [
              Metin(
                "Tüm ayrıntılar için teşekkürler! Evcil hayvanınızı aşağıdaki bilgilerle birlikte kontrol edeceğiz.",
                stil: Theme.of(context).textTheme.caption,
              ),
              kart(
                çocuk: Sütun(
                  çocuklar: [
                    Text('Ad: ${firstName.text}'),
                    Text('Soyadı: ${lastName.text}rn'),
                    Text('Evcil hayvan türü: ${_petType}'),
                    Text('Yanıt 1: ${questionResponses[0].text}'),
                    Text('Yanıt 2: ${questionResponses[1].text}'),
                    Text('Yanıt 3: ${questionResponses[2].text}'),
                  ],
                ),
              )
            ],
          ),
        );
      }
    },
    çocuk: Metin('KAYIT'))

Flutter'da manuel olarak form oluşturmayla ilgili sorunlar

Flutter'da formları kullanmak aşırı derecede zor değil, ancak kendi formlarımızı el işçiliği ile yapmak biraz zahmetli olabilir. Neden böyle olduğunu çözelim.

İlk olarak, bir alandan metin almak veya alanın girişini silmek istiyorsanız, her alan için kendi TextEditingController oluşturmanız gerekir. Kendinizi takip etmeniz gereken bunlardan birkaçıyla nasıl sonuçlanabileceğinizi görmek kolaydır.

İkincisi, bir sayının doğru olup olmadığını kontrol etmek gibi basit şeyler için kendi doğrulama mantığınızı yazmanız gerekir.

Son olarak, bu yaklaşım oldukça fazla ortak kod ile sonuçlanır. Bir veya iki metin alanı için o kadar da kötü değil, ancak nasıl zayıf ölçeklenebileceğini görmek kolay.

Dikkate alınması gereken iki reaktif form Flutter paketi seçeneği

Bu süreci kolaylaştıracak bir paket bulma yolculuğuna çıksaydık ve aklımızda “reaktif formlar” olsaydı, muhtemelen reactive_forms Flutter paketi ile oldukça hızlı bir şekilde karşılaşırdık. Yine de, uygulamamda reaktif formlar oluşturmak için kullanacağım paket değil.

Neden?

Pekala, pub.dev'deki ilk cümle bize Reaktif Formların “… Form girdilerini ve doğrulamalarını işlemeye yönelik, Angular'ın Reaktif Formlarından büyük ölçüde ilham alan model odaklı bir yaklaşım” olduğunu söylüyor.

Bundan dolayı, reactive_forms paketinde kullanılan zihniyetin Angular'da bulduğumuza benzer olacağını belirleyebiliriz.

Angular'ı zaten biliyorsak, bu muhtemelen reactive_forms kullanmak için daha fazla nedendir. Ancak Angular'ı bilmiyorsak, formlarımız içinde tepkiselliğe ulaşmanın en basit yolu ile daha çok ilgileniyoruz.

Deneyimlerime göre, flutter_form_builder paketini form oluşturmanın daha kolay ve genişletilebilir bir yolu olarak görüyorum.

Elbette, her iki paketi de araştırmanızı ve tercih ettiğiniz birini seçmenizi tavsiye ederim, çünkü bir paket diğerinden "daha iyi" olmayabilir, ancak bunlar benzer bir sonuca ulaşmanın iki farklı yolunu temsil eder.

Reaktif formlar oluşturmak için flutter_form_builder kullanma

Şimdi formlarımızı oluşturmak için flutter_form_builder paketini kullanalım. Bu, yazmamız gereken kod miktarını azaltabilir, yazdığımız kodu anlamayı kolaylaştırabilir ve ayrıca bizi kendi doğrulama mantığımızı yazmaktan kurtarabilir.

İlk olarak, pubspec.yaml flutter_form_builder paketine bir bağımlılık ekleyeceğiz:

 flutter_form_builder: ^7.4.0

Bu kurulumla, flutter_form_builder kullanmak için formlarımızı yeniden uygulayalım.

Formumuzda kullanmayı düşündüğümüz alanlar için bazı isimler eklememiz gerekecek. Bunları daha sonra FormBuilderTextField onlara bağlamamız gerekeceğinden, bizim için mantıklı olan bir değişken adına ayarlamalıyız.

 final String FIRST_NAME = 'FirstName';
final String LAST_NAME = 'LastName';
son Dize PHONE_NUMBER = 'TelefonNumarası';
final String PET_CHOICE = 'PetChoice';
son Dize QUESTION_ANSWER_1 = 'QuestionAnswer1';
son Dize QUESTION_ANSWER_2 = 'QuestionAnswer2';
son Dize QUESTION_ANSWER_3 = 'QuestionAnswer3';

Ayrıca formumuzun yakaladığı ayrıntıları saklamak için bir GlobalKey<FormBuilderState> belirtmemiz gerekiyor.

 final _fbKey = GlobalKey<FormBuilderState>();

Sonraki büyük değişiklik, formumuzu bir Form sarmak yerine, onu bir FormBuilder ve FormBuilder için bir anahtar belirtmemizdir.

 FormBuilder(
  anahtar: _fbKey,
  alt: Sütun(çocuklar: [...buraya çocuk widget'ları])
)

Bu, FormBuilder formdaki değerleri bu anahtarda depolayacağı anlamına gelir, böylece bunları daha sonra kolayca alabiliriz.

Temel form girişlerini ayarlama

Normalde, hangi TextEditingController kullanılması gerektiğini manuel olarak belirlemekten ve doğrulama gibi şeyleri manuel olarak ayarlamaktan sorumlu oluruz. Ancak flutter_form_builder ile bu iki şey önemsiz hale gelir.

Bir metin giriş alanı için alanın name parametresini ve alanı etiketlemek istiyorsak dekorasyonunu belirtiyoruz. Ayrıca, kendimizinkini yazmak yerine mevcut bir doğrulayıcı kümesinden seçim yapabiliriz. Bu, ad ve soyadı giriş alanlarımızın şöyle göründüğü anlamına gelir:

 FormBuilderTextField(
  isim: FIRST_NAME,
  dekorasyon: InputDecoration(labelText: 'First Name'),
  doğrulayıcı: FormBuilderValidators.required(),
),

Telefon numarası alanımız için kendi doğrulayıcımızı yazmak yerine, FormBuilderValidators.numeric() doğrulayıcısını kullanabiliriz:

 FormBuilderTextField(
  isim: PHONE_NUMBER,
  doğrulayıcı: FormBuilderValidators.numeric(),
  dekorasyon: InputDecoration(labelText: 'Telefon numarası'),
  autovalidateMode: AutovalidateMode.always,
),

Evcil hayvan türü seçiciyi ayarlama

Şimdi kullanıcıya Flutter uygulamamızdaki uygun radyo düğmesini seçerek seçebileceği evcil hayvan türü seçeneklerinin bir listesini vermek istiyoruz. Bu listeyi, sağlanan numaralandırma setimizden programlı olarak oluşturabiliriz.

Bu, programımızda enumumuza seçenekler eklersek veya çıkarırsak, seçeneklerin formumuz içinde de değişeceği anlamına gelir. Bu, listeyi kendimiz elle tutmaktan daha kolay olacaktır.

 FormBuilderRadioGroup<PetType>(
  onChanged: (val) {
    yazdır(val);
    setState(() {
      _petType = val;
    });
  },
  isim: PET_CHOICE,
  doğrulayıcı: FormBuilderValidators.required(),
  oryantasyon: OptionsOrientation.vertical, // Seçenekleri dikey olarak yerleştir
  seçenekler: [
    // PetType numaralandırmasındaki tüm seçenekleri al ve onları seçenek olarak göster
    // Seçeneklerin ilk harflerini de büyük yaz
    ...PetType.values.map(
      (e) => FormBuilderFieldOption(
        değer: e,
        çocuk: Metin(
          tarifEnum(e).replaceFirst(
            tarifEnum(e)[0],
            tarifEnum(e)[0].toUpperCase(),
          ),
        ),
      ),
    ),
  ],
),

Sonunda üç soruyu ayarlama

Oluşturucu yöntemimiz, Flutter formumuzun bu bölümü için birkaç önemli farklılık dışında büyük ölçüde aynı kalır: şimdi girdilerimiz için FormBuilderTextField sınıfını kullanıyoruz ve bunları form içindeki uygun girdiyle name parametresi aracılığıyla ilişkilendiriyoruz.

 vaka PetType.cat:
  dönüş Sütunu(
    çocuklar: [
      Text("Aa, bu bir kedi!"),
      FormBuilderTextField(
        ad: QUESTION_ANSWER_1,
        dekorasyon: InputDecoration(labelText: 'Kediyi okşayabilir miyiz?'),
      ),
      FormBuilderTextField(
        isim: QUESTION_ANSWER_2,
        dekorasyon: InputDecoration(labelText: 'Üzerine küçük bir kıyafet koyabilir miyiz?'),
      ),
      FormBuilderTextField(
        isim: QUESTION_ANSWER_3,
        dekorasyon: InputDecoration(labelText: 'Kutulara atlamayı sever mi?'),
      ),
    ],
  );

Formdan değerleri doğrulama ve alma

Reaktif Flutter form kurulumumuzla, şimdi yapmamız gereken son iki şey var: formun içinde kullanılabilir veriler olduğunu doğrulamak ve bu değerleri formdan almak.

Neyse ki, doğrulama gereksinimlerini her alanın kendi içinde belirlediğimiz için doğrulama işlemimiz oldukça basit hale geliyor:

 son geçerli = _fbKey.currentState?.saveAndValidate() ?? yanlış;

Bu işlemin sonucu, formumuzun mevcut durumu null değilse ve şu anda valid olarak kabul edilirse – yani tüm form alanları doğrulamayı geçtiyse – form geçerli olarak kabul edilir. currentState null ise veya form invalid , bu değişken bunun yerine false .

Başarılı bir sonuç durumunda, değerler kullanıcıya gösterilecektir. _fbKey nesnesi içindeki currentState nesnesine erişerek form içindeki değerlere kolayca erişebiliriz.

 gösterDiyalog(
  bağlam: bağlam,
  oluşturucu: (bağlam) => SimpleDialog(
    içerik Doldurma: EdgeInsets.all(20),
    başlık: Metin("Her şey bitti!"),
    çocuklar: [
      Metin(
        "Tüm ayrıntılar için teşekkürler! Evcil hayvanınızı aşağıdaki bilgilerle birlikte kontrol edeceğiz.",
        stil: Theme.of(context).textTheme.caption,
      ),
      kart(
        çocuk: Sütun(
          çocuklar: [
            // Kullanmakta sorun yok ! currentState ile operatör, çünkü biz
            // formu yaptığımızda zaten boş olmadığını kontrol ettik
            // doğrulama
            Text('Ad: ${_fbKey.currentState!.value[FIRST_NAME]}'),
            Text('Soyadı: ${_fbKey.currentState!.value[LAST_NAME]}'),
            Text('Sayı: ${_fbKey.currentState!.value[PHONE_NUMBER]}'),
            Text('Evcil hayvan türü: ${_fbKey.currentState!.value[PET_CHOICE]}'),
            Text('Yanıt 1: ${_fbKey.currentState!.value[QUESTION_ANSWER_1]}'),
            Text('Yanıt 2: ${_fbKey.currentState!.value[QUESTION_ANSWER_2]}'),
            Text('Yanıt 3: ${_fbKey.currentState!.value[QUESTION_ANSWER_3]}'),
          ],
        ),
      )
    ],
  ),
);

toparlamak

Gördüğümüz gibi, Flutter'da reaktif formlar oluşturmak için flutter_form_builder kullanmak, geliştiriciler olarak bizler için birçok iyileştirme sağlayabilir. Her zaman olduğu gibi, projenizde flutter_form_builder nasıl kullanabileceğinizi görmek için Github'daki bu projenin koduna göz atabilirsiniz .

Projenin tam olarak nasıl değiştiğini görmek için iki taahhüt arasında karşılaştırma yapmak için aşağıdaki bağlantıları da kullanabilirsiniz:

flutter_form_builder olarak sunduğu birkaç farklı alan türü vardır, bu nedenle ihtiyacınıza göre her zaman doğru alan türünü kullanabilmelisiniz.

Eğlenin ve bu formları oluşturmanın tadını çıkarın!

Flutter'da reaktif formlar oluşturma yazısı ilk olarak LogRocket Blog'da göründü.

etiketlerETİKETLER
Üzgünüm, bu içerik için hiç etiket bulunmuyor.

Sıradaki içerik:

Flutter'da reaktif formlar oluşturma