Basics

Formlar

Giris

Nylo Website v7, NyFormWidget etrafinda olusturulmus bir form sistemi sunar. Form sinfiniz NyFormWidget sinifini genisletir ve kendisi widget'tir -- ayri bir wrapper gerekmez. Formlar yerlesik dogrulama, bircok alan turu, stilleme ve veri yonetimini destekler.

import 'package:nylo_framework/nylo_framework.dart';

// 1. Define a form
class LoginForm extends NyFormWidget {
  LoginForm({super.key, super.submitButton, super.onSubmit, super.onFailure});

  @override
  fields() => [
    Field.email("Email", validator: FormValidator.email()),
    Field.password("Password", validator: FormValidator.password()),
  ];

  static NyFormActions get actions => const NyFormActions('LoginForm');
}

// 2. Display and submit it
LoginForm(
  submitButton: Button.primary(text: "Login"),
  onSubmit: (data) {
    print(data); // {email: "...", password: "..."}
  },
)

Form Olusturma

Yeni bir form olusturmak icin Metro CLI kullanin:

metro make:form LoginForm

Bu, lib/app/forms/login_form.dart dosyasini olusturur:

import 'package:nylo_framework/nylo_framework.dart';

class LoginForm extends NyFormWidget {
  LoginForm({super.key, super.submitButton, super.onSubmit, super.onFailure});

  @override
  fields() => [
    Field.email("Email", validator: FormValidator.email()),
    Field.password("Password", validator: FormValidator.password()),
  ];

  static NyFormActions get actions => const NyFormActions('LoginForm');
}

Formlar NyFormWidget sinifini genisletir ve form alanlarini tanimlamak icin fields() metodunu gecersiz kilar. Her alan Field.text(), Field.email() veya Field.password() gibi adlandirilmis bir kurucu kullanir. static NyFormActions get actions getter'i, uygulamanizin herhangi bir yerinden formla etkilesim kurmak icin uygun bir yol saglar.

Form Goruntuleme

Form sinfiniz NyFormWidget sinifini genislettigi icin, kendisi widget'tir. Dogrudan widget agacinizda kullanin:

@override
Widget view(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: LoginForm(
        submitButton: Button.primary(text: "Submit"),
        onSubmit: (data) {
          print(data);
        },
      ),
    ),
  );
}

Form Gonderme

Bir formu gondermenin uc yolu vardir:

onSubmit ve submitButton kullanma

Formu olustururken onSubmit ve bir submitButton gecirin. Nylo Website, gonder dugmesi olarak calisan onceden olusturulmus dugmeler saglar:

LoginForm(
  submitButton: Button.primary(text: "Submit"),
  onSubmit: (data) {
    print(data); // {email: "...", password: "..."}
  },
  onFailure: (errors) {
    print(errors.first.rule.getMessage());
  },
)

Mevcut dugme stilleri: Button.primary, Button.secondary, Button.outlined, Button.textOnly, Button.icon, Button.gradient, Button.rounded, Button.transparency.

NyFormActions kullanma

Herhangi bir yerden gondermek icin actions getter'ini kullanin:

LoginForm.actions.submit(
  onSuccess: (data) {
    print(data);
  },
  onFailure: (errors) {
    print(errors.first.rule.getMessage());
  },
  showToastError: true,
);

NyFormWidget.submit() statik metodu kullanma

Bir formu adiyla herhangi bir yerden gonderin:

NyFormWidget.submit("LoginForm",
  onSuccess: (data) {
    print(data);
  },
  onFailure: (errors) {
    print(errors.first.rule.getMessage());
  },
  showToastError: true,
);

Gonderildiginde, form tum alanlari dogrular. Gecerliyse, onSuccess alan verilerinin Map<String, dynamic> degeriyle cagrilir (anahtarlar alan adlarinin snake_case versiyonlaridir). Gecersizse, varsayilan olarak bir toast hatasi gosterilir ve saglanmissa onFailure cagrilir.

Alan Turleri

Nylo Website v7, Field sinifinda adlandirilmis kurucular araciligiyla 22 alan turu saglar. Tum alan kuruculari su ortak parametreleri paylasir:

Parametre Tur Varsayilan Aciklama
key String Zorunlu Alan tanimlayicisi (konumsal)
label String? null Ozel goruntuleme etiketi (varsayilan olarak anahtar baslik buyuklugunde)
value dynamic null Baslangic degeri
validator FormValidator? null Dogrulama kurallari
autofocus bool false Yuklemede otomatik odaklanma
dummyData String? null Test/gelistirme verileri
header Widget? null Alanin ustunde goruntulenen widget
footer Widget? null Alanin altinda goruntulenen widget
titleStyle TextStyle? null Ozel etiket metin stili
hidden bool false Alani gizle
readOnly bool? null Alani salt okunur yap
style FieldStyle? Degisir Alana ozgu stil yapilandirmasi
onChanged Function(dynamic)? null Deger degisikligi callback'i

Metin Alanlari

Field.text("Name")

Field.text("Name",
  value: "John",
  validator: FormValidator.notEmpty(),
  autofocus: true,
)

Stil turu: FieldStyleTextField

Sayi Alanlari

Field.number("Age")

// Decimal numbers
Field.number("Score", decimal: true)

decimal parametresi ondalik giris izin verilip verilmeyecegini kontrol eder. Stil turu: FieldStyleTextField

Sifre Alanlari

Field.password("Password")

// With visibility toggle
Field.password("Password", viewable: true)

viewable parametresi bir goster/gizle gecis dugmesi ekler. Stil turu: FieldStyleTextField

E-posta Alanlari

Field.email("Email", validator: FormValidator.email())

Otomatik olarak e-posta klavye turunu ayarlar ve bosluklari filtreler. Stil turu: FieldStyleTextField

URL Alanlari

Field.url("Website", validator: FormValidator.url())

URL klavye turunu ayarlar. Stil turu: FieldStyleTextField

Metin Alani (Cok Satirli)

Field.textArea("Description")

Cok satirli metin girisi. Stil turu: FieldStyleTextField

Telefon Numarasi Alanlari

Field.phoneNumber("Mobile Phone")

Telefon numarasi girisini otomatik olarak bicimlendirir. Stil turu: FieldStyleTextField

Kelimeleri Buyuk Harfle Baslatma

Field.capitalizeWords("Full Name")

Her kelimenin ilk harfini buyuk yapar. Stil turu: FieldStyleTextField

Cumleleri Buyuk Harfle Baslatma

Field.capitalizeSentences("Bio")

Her cumlenin ilk harfini buyuk yapar. Stil turu: FieldStyleTextField

Tarih Alanlari

Field.date("Birthday")

Field.date("Birthday",
  dummyData: "1990-01-01",
  style: FieldStyleDateTimePicker(
    firstDate: DateTime(1900),
    lastDate: DateTime.now(),
  ),
)

Bir tarih secici acar. Stil turu: FieldStyleDateTimePicker

TarihSaat Alanlari

Field.datetime("Check in Date")

Field.datetime("Appointment", dummyData: "2025-01-01 10:00")

Bir tarih ve saat secici acar. Stil turu: FieldStyleDateTimePicker

Maskeli Giris Alanlari

Field.mask("Phone", mask: "(###) ###-####")

Field.mask("Credit Card", mask: "#### #### #### ####")

Field.mask("Custom Code",
  mask: "AA-####",
  match: r'[\w\d]',
  maskReturnValue: true, // Returns the formatted value
)

Maskedeki # karakteri kullanici girisiyle degistirilir. Izin verilen karakterleri kontrol etmek icin match kullanin. maskReturnValue true oldugunda, dondurulen deger maske bicimlendirmesini icerir.

Para Birimi Alanlari

Field.currency("Price", currency: "usd")

currency parametresi zorunludur ve para birimi bicimini belirler. Stil turu: FieldStyleTextField

Onay Kutusu Alanlari

Field.checkbox("Accept Terms")

Field.checkbox("Agree to terms",
  header: Text("Terms and conditions"),
  footer: Text("You must agree to continue."),
  validator: FormValidator.booleanTrue(message: "You must accept the terms"),
)

Stil turu: FieldStyleCheckbox

Anahtar Kutusu Alanlari

Field.switchBox("Enable Notifications")

Stil turu: FieldStyleSwitchBox

Secici Alanlari

Field.picker("Category",
  options: FormCollection.from(["Electronics", "Clothing", "Books"]),
)

// With key-value pairs
Field.picker("Country",
  options: FormCollection.fromMap({
    "us": "United States",
    "ca": "Canada",
    "uk": "United Kingdom",
  }),
)

options parametresi bir FormCollection gerektirir (ham liste degil). Ayrintilar icin FormCollection bolumune bakin. Stil turu: FieldStylePicker

Radyo Alanlari

Field.radio("Newsletter",
  options: FormCollection.fromMap({
    "Yes": "Yes, I want to receive newsletters",
    "No": "No, I do not want to receive newsletters",
  }),
)

options parametresi bir FormCollection gerektirir. Stil turu: FieldStyleRadio

Cip Alanlari

Field.chips("Tags",
  options: FormCollection.from(["Featured", "Sale", "New"]),
)

// With key-value pairs
Field.chips("Engine Size",
  options: FormCollection.fromMap({
    "125": "125cc",
    "250": "250cc",
    "500": "500cc",
  }),
)

Cip widget'lari araciligiyla coklu secim yapilmasini saglar. options parametresi bir FormCollection gerektirir. Stil turu: FieldStyleChip

Kaydirici Alanlari

Field.slider("Rating",
  label: "Rate us",
  validator: FormValidator.minValue(4, message: "Rating must be at least 4"),
  style: FieldStyleSlider(
    min: 0,
    max: 10,
    divisions: 10,
    activeColor: Colors.blue,
    inactiveColor: Colors.grey,
  ),
)

Stil turu: FieldStyleSlider -- min, max, divisions, renkler, deger gosterimi ve daha fazlasini yapilandirin.

Aralik Kaydirici Alanlari

Field.rangeSlider("Price Range",
  style: FieldStyleRangeSlider(
    min: 0,
    max: 1000,
    divisions: 20,
    activeColor: Colors.blue,
    inactiveColor: Colors.grey,
  ),
)

Bir RangeValues nesnesi dondurur. Stil turu: FieldStyleRangeSlider

Ozel Alanlar

Kendi durum bilgili widget'inizi saglamak icin Field.custom() kullanin:

Field.custom("My Field",
  child: MyCustomFieldWidget(),
)

child parametresi NyFieldStatefulWidget sinifini genisleten bir widget gerektirir. Bu, alanin render edilmesi ve davranisi uzerinde tam kontrol saglar.

Widget Alanlari

Form alani olmadan form icine herhangi bir widget yerlestirmek icin Field.widget() kullanin:

Field.widget(child: Divider())

Field.widget(child: Text("Section Header", style: TextStyle(fontSize: 18)))

Widget alanlari dogrulama veya veri toplamaya katilmaz. Yalnizca duzen amaclidir.

FormCollection

Secici, radyo ve cip alanlari, secenekleri icin bir FormCollection gerektirir. FormCollection, farkli secenek bicimlerini islemek icin birlesik bir arayuz saglar.

FormCollection Olusturma

// From a list of strings (value and label are the same)
FormCollection.from(["Red", "Green", "Blue"])

// Same as above, explicit
FormCollection.fromArray(["Red", "Green", "Blue"])

// From a map (key = value, value = label)
FormCollection.fromMap({
  "us": "United States",
  "ca": "Canada",
})

// From structured data (useful for API responses)
FormCollection.fromKeyValue([
  {"value": "en", "label": "English"},
  {"value": "es", "label": "Spanish"},
])

FormCollection.from(), veri bicimini otomatik olarak algilar ve uygun kurucuya yonlendirir.

FormOption

Bir FormCollection icindeki her secenek, value ve label ozelliklerine sahip bir FormOption'dir:

FormOption option = FormOption(value: "us", label: "United States");
print(option.value); // "us"
print(option.label); // "United States"

Secenekleri Sorgulama

FormCollection options = FormCollection.fromMap({"us": "United States", "ca": "Canada"});

options.getByValue("us");          // FormOption(value: us, label: United States)
options.getLabelByValue("us");     // "United States"
options.containsValue("ca");      // true
options.searchByLabel("can");      // [FormOption(value: ca, label: Canada)]
options.values;                    // ["us", "ca"]
options.labels;                    // ["United States", "Canada"]

Form Dogrulama

FormValidator ile validator parametresini kullanarak herhangi bir alana dogrulama ekleyin:

// Named constructor
Field.email("Email", validator: FormValidator.email())

// Chained rules
Field.text("Username",
  validator: FormValidator()
    .notEmpty()
    .minLength(3)
    .maxLength(20)
)

// Password with strength level
Field.password("Password",
  validator: FormValidator.password(strength: 2)
)

// Boolean validation
Field.checkbox("Terms",
  validator: FormValidator.booleanTrue(message: "You must accept the terms")
)

// Custom inline validation
Field.number("Age",
  validator: FormValidator.custom(
    message: "Age must be between 18 and 100",
    validate: (data) {
      int? age = int.tryParse(data.toString());
      return age != null && age >= 18 && age <= 100;
    },
  )
)

Bir form gonderildiginde, tum dogrulayicilar kontrol edilir. Herhangi biri basarisiz olursa, ilk hata mesajini gosteren bir toast hatasi goruntulenir ve onFailure callback'i cagrilir.

Ayrica bakin: Kullanilabilir dogrulayicilarin tam listesi icin Dogrulama sayfasina bakin.

Form Verilerini Yonetme

Baslangic Verileri

Bir forma baslangic verileri ayarlamanin iki yolu vardir.

Secenek 1: Form sinifinizda init getter'ini gecersiz kilin

class EditAccountForm extends NyFormWidget {
  EditAccountForm({super.key, super.submitButton, super.onSubmit, super.onFailure});

  @override
  Function()? get init => () async {
    final user = await api<ApiService>((request) => request.getUserData());

    return {
      "First Name": user?.firstName,
      "Last Name": user?.lastName,
    };
  };

  @override
  fields() => [
    Field.text("First Name"),
    Field.text("Last Name"),
  ];

  static NyFormActions get actions => const NyFormActions('EditAccountForm');
}

init getter'i senkron bir Map veya asenkron bir Future<Map> dondurebilir. Anahtarlar, snake_case normalizasyonu kullanilarak alan adlariyla eslestirilir, bu nedenle "First Name" anahtari "First Name" adli bir alanla eslesir.

Secenek 2: Form widget'ina initialData gecirin

EditAccountForm(
  initialData: {
    "first_name": "John",
    "last_name": "Doe",
  },
)

Alan Degerlerini Ayarlama

Herhangi bir yerden alan degerlerini ayarlamak icin NyFormActions kullanin:

// Set a single field value
EditAccountForm.actions.updateField("First Name", "Jane");

Alan Seceneklerini Ayarlama

Secici, cip veya radyo alanlarindaki secenekleri dinamik olarak guncelleyin:

EditAccountForm.actions.setOptions("Category", FormCollection.from(["New Option 1", "New Option 2"]));

Form Verilerini Okuma

Form verileri, form gonderildiginde onSubmit callback'i araciligiyla veya gercek zamanli guncellemeler icin onChanged callback'i araciligiyla erisilir:

EditAccountForm(
  onSubmit: (data) {
    // data is a Map<String, dynamic>
    // {first_name: "Jane", last_name: "Doe", email: "jane@example.com"}
    print(data);
  },
  onChanged: (Field field, dynamic value) {
    print("${field.key} changed to: $value");
  },
)

Verileri Temizleme

// Clear all fields
EditAccountForm.actions.clear();

// Clear a specific field
EditAccountForm.actions.clearField("First Name");

Alanlari Guncelleme

// Update a field value
EditAccountForm.actions.updateField("First Name", "Jane");

// Refresh the form UI
EditAccountForm.actions.refresh();

// Refresh form fields (re-calls fields())
EditAccountForm.actions.refreshForm();

Gonder Dugmesi

Formu olustururken bir submitButton ve onSubmit callback'i gecirin:

UserInfoForm(
  submitButton: Button.primary(text: "Submit"),
  onSubmit: (data) {
    print(data);
  },
  onFailure: (errors) {
    print(errors.first.rule.getMessage());
  },
)

submitButton otomatik olarak form alanlarinin altinda goruntulenir. Yerlesik dugme stillerinden herhangi birini veya ozel bir widget kullanabilirsiniz.

Herhangi bir widget'i footer olarak gecirerek gonder dugmesi olarak da kullanabilirsiniz:

UserInfoForm(
  onSubmit: (data) {
    print(data);
  },
  footer: ElevatedButton(
    onPressed: () {
      UserInfoForm.actions.submit(
        onSuccess: (data) {
          print(data);
        },
      );
    },
    child: Text("Submit"),
  ),
)

Form Duzeni

Alanlari yan yana yerlestirmek icin bir List icine sarin:

@override
fields() => [
  // Single field (full width)
  Field.text("Title"),

  // Two fields in a row
  [
    Field.text("First Name"),
    Field.text("Last Name"),
  ],

  // Another single field
  Field.textArea("Bio"),

  // Slider and range slider in a row
  [
    Field.slider("Rating", style: FieldStyleSlider(min: 0, max: 10)),
    Field.rangeSlider("Budget", style: FieldStyleRangeSlider(min: 0, max: 1000)),
  ],

  // Embed a non-field widget
  Field.widget(child: Divider()),

  Field.email("Email"),
];

Bir List icindeki alanlar, esit Expanded genisliklere sahip bir Row icinde render edilir. Alanlar arasindaki bosluk, NyFormWidget uzerindeki crossAxisSpacing parametresiyle kontrol edilir.

Alan Gorunurlugu

Field uzerindeki hide() ve show() metotlarini kullanarak alanlari programatik olarak gosterin veya gizleyin. Alanlara form sinifinizin icinden veya onChanged callback'i araciligiyla erisebilirsiniz:

// Inside your NyFormWidget subclass or onChanged callback
Field nameField = ...;

// Hide the field
nameField.hide();

// Show the field
nameField.show();

Gizli alanlar arayuzde render edilmez ancak formun alan listesinde var olmaya devam eder.

Alan Stilleri

Her alan turunun stilleme icin karsilik gelen bir FieldStyle alt sinifi vardir:

Alan Turu Stil Sinifi
Text, Email, Password, Number, URL, TextArea, PhoneNumber, Currency, Mask, CapitalizeWords, CapitalizeSentences FieldStyleTextField
Date, DateTime FieldStyleDateTimePicker
Picker FieldStylePicker
Checkbox FieldStyleCheckbox
Switch Box FieldStyleSwitchBox
Radio FieldStyleRadio
Chip FieldStyleChip
Slider FieldStyleSlider
Range Slider FieldStyleRangeSlider

Herhangi bir alanin style parametresine bir stil nesnesi gecirin:

Field.text("Name",
  style: FieldStyleTextField(
    filled: true,
    fillColor: Colors.grey.shade100,
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
    contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
    prefixIcon: Icon(Icons.person),
  ),
)

Field.slider("Rating",
  style: FieldStyleSlider(
    min: 0,
    max: 10,
    divisions: 10,
    activeColor: Colors.blue,
    showValue: true,
  ),
)

Field.chips("Tags",
  options: FormCollection.from(["Sale", "New", "Featured"]),
  style: FieldStyleChip(
    selectedColor: Colors.blue,
    checkmarkColor: Colors.white,
    spacing: 8.0,
    runSpacing: 8.0,
  ),
)

NyFormWidget Statik Metotlari

NyFormWidget, uygulamanizin herhangi bir yerinden formlarla ada gore etkilesim kurmak icin statik metotlar saglar:

Metot Aciklama
NyFormWidget.submit(name, onSuccess:, onFailure:, showToastError:) Bir formu adiyla gonder
NyFormWidget.stateRefresh(name) Formun arayuz durumunu yenile
NyFormWidget.stateSetValue(name, key, value) Form adiyla alan degerini ayarla
NyFormWidget.stateSetOptions(name, key, options) Form adiyla alan seceneklerini ayarla
NyFormWidget.stateClearData(name) Form adiyla tum alanlari temizle
NyFormWidget.stateRefreshForm(name) Form alanlarini yenile (fields() yeniden cagirir)
// Submit a form named "LoginForm" from anywhere
NyFormWidget.submit("LoginForm", onSuccess: (data) {
  print(data);
});

// Update a field value remotely
NyFormWidget.stateSetValue("LoginForm", "Email", "new@email.com");

// Clear all form data
NyFormWidget.stateClearData("LoginForm");

Ipucu: Bu statik metotlari dogrudan cagirmak yerine NyFormActions (asagiya bakin) kullanmayi tercih edin -- daha kisa ve daha az hataya aciktir.

NyFormWidget Kurucu Referansi

NyFormWidget sinifini genisletirken, gecebileceginiz kurucu parametreleri sunlardir:

LoginForm(
  Key? key,
  double crossAxisSpacing = 10,  // Horizontal spacing between row fields
  double mainAxisSpacing = 10,   // Vertical spacing between fields
  Map<String, dynamic>? initialData, // Initial field values
  Function(Field field, dynamic value)? onChanged, // Field change callback
  Widget? header,                // Widget above the form
  Widget? submitButton,          // Submit button widget
  Widget? footer,                // Widget below the form
  double headerSpacing = 10,     // Spacing after header
  double submitButtonSpacing = 10, // Spacing after submit button
  double footerSpacing = 10,     // Spacing before footer
  LoadingStyle? loadingStyle,    // Loading indicator style
  bool locked = false,           // Makes form read-only
  Function(dynamic data)? onSubmit,   // Called with form data on successful validation
  Function(dynamic error)? onFailure, // Called with errors on failed validation
)

onChanged callback'i, degisen Field ve yeni degerini alir:

LoginForm(
  onChanged: (Field field, dynamic value) {
    print("${field.key} changed to: $value");
  },
)

NyFormActions

NyFormActions, uygulamanizin herhangi bir yerinden bir formla etkilesim kurmak icin uygun bir yol saglar. Form sinifinizda statik getter olarak tanimlayin:

class LoginForm extends NyFormWidget {
  LoginForm({super.key, super.submitButton, super.onSubmit, super.onFailure});

  @override
  fields() => [
    Field.email("Email", validator: FormValidator.email()),
    Field.password("Password", validator: FormValidator.password()),
  ];

  static NyFormActions get actions => const NyFormActions('LoginForm');
}

Mevcut Aksiyonlar

Metot Aciklama
actions.updateField(key, value) Bir alanin degerini ayarla
actions.clearField(key) Belirli bir alani temizle
actions.clear() Tum alanlari temizle
actions.refresh() Formun arayuz durumunu yenile
actions.refreshForm() fields() yeniden cagir ve yeniden olustur
actions.setOptions(key, options) Secici/cip/radyo alanlarinda secenekleri ayarla
actions.submit(onSuccess:, onFailure:, showToastError:) Dogrulama ile gonder
// Update a field value
LoginForm.actions.updateField("Email", "new@email.com");

// Clear all form data
LoginForm.actions.clear();

// Submit the form
LoginForm.actions.submit(
  onSuccess: (data) {
    print(data);
  },
);

NyFormWidget Gecersiz Kilmalari

NyFormWidget alt sinifinizdaki gecersiz kilabilecek metotlar:

Gecersiz Kilma Aciklama
fields() Form alanlarini tanimlayin (zorunlu)
init Baslangic verileri saglayin (senkron veya asenkron)
onChange(field, data) Alan degisikliklerini dahili olarak yonetin

Tum Alan Turleri Referansi

Kurucu Anahtar Parametreler Aciklama
Field.text() -- Standart metin girisi
Field.email() -- Klavye turlu e-posta girisi
Field.password() viewable Istege bagli gorunurluk gecisli sifre
Field.number() decimal Sayisal giris, istege bagli ondalik
Field.currency() currency (zorunlu) Para birimi bicimli giris
Field.capitalizeWords() -- Baslik buyuklugunde metin girisi
Field.capitalizeSentences() -- Cumle buyuklugunde metin girisi
Field.textArea() -- Cok satirli metin girisi
Field.phoneNumber() -- Otomatik bicimli telefon numarasi
Field.url() -- Klavye turlu URL girisi
Field.mask() mask (zorunlu), match, maskReturnValue Maskeli metin girisi
Field.date() -- Tarih secici
Field.datetime() -- Tarih ve saat secici
Field.checkbox() -- Boolean onay kutusu
Field.switchBox() -- Boolean gecis anahtari
Field.picker() options (zorunlu FormCollection) Listeden tekli secim
Field.radio() options (zorunlu FormCollection) Radyo dugme grubu
Field.chips() options (zorunlu FormCollection) Coklu secim cipleri
Field.slider() -- Tekli deger kaydiricisi
Field.rangeSlider() -- Aralik deger kaydiricisi
Field.custom() child (zorunlu NyFieldStatefulWidget) Ozel durum bilgili widget
Field.widget() child (zorunlu Widget) Herhangi bir widget yerlestir (alan disi)