Validasi Form dengan FormKey
Validasi banyak field sekaligus dengan Form, GlobalKey, dan validator yang memberi pesan error jelas.
Kenapa butuh Form?
TextField satuan tidak punya mekanisme validasi terpusat. Widget Form membungkus beberapa TextFormField dan menyediakan method validate() untuk memeriksa semuanya sekaligus lewat GlobalKey<FormState>.
Struktur form validasi
class _FormKasirState extends State<FormKasir> {
final _formKey = GlobalKey<FormState>();
final _namaController = TextEditingController();
final _hargaController = TextEditingController();
@override
void dispose() {
_namaController.dispose();
_hargaController.dispose();
super.dispose();
}
void _simpan() {
if (_formKey.currentState!.validate()) {
debugPrint('Form valid, simpan: ${_namaController.text}');
} else {
debugPrint('Form belum valid');
}
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _namaController,
decoration: const InputDecoration(labelText: 'Nama produk'),
validator: (nilai) {
if (nilai == null || nilai.trim().isEmpty) {
return 'Nama produk wajib diisi';
}
if (nilai.trim().length < 3) {
return 'Nama minimal 3 karakter';
}
return null;
},
),
const SizedBox(height: 12),
TextFormField(
controller: _hargaController,
decoration: const InputDecoration(labelText: 'Harga'),
keyboardType: TextInputType.number,
validator: (nilai) {
final harga = int.tryParse(nilai ?? '');
if (harga == null || harga <= 0) {
return 'Harga harus angka lebih dari 0';
}
return null;
},
),
const SizedBox(height: 16),
ElevatedButton(onPressed: _simpan, child: const Text('Simpan')),
],
),
);
}
}Aturan validator sederhana: kembalikan string error kalau tidak valid, kembalikan null kalau valid.
Autovalidate: validasi real-time
Secara default validasi jalan saat validate() dipanggil. Untuk pengalaman lebih responsif, set autovalidateMode: AutovalidateMode.onUserInteraction pada Form, sehingga error muncul setelah user mulai berinteraksi, bukan sejak awal yang terasa menghakimi.
Menyimpan dengan onSaved
Alternatif controller adalah onSaved yang dipanggil saat _formKey.currentState!.save(). Cocok untuk form sederhana, tapi untuk form kompleks controller lebih fleksibel karena nilainya bisa dibaca kapan saja.
Catatan teknis:
_formKey.currentState!memakai null assertion. Ia aman dipanggil dari event handler setelah form ter-render, tapi jangan dipanggil diinitStatekarena form belum dibangun dan currentState masih null. Kalau butuh validasi otomatis saat halaman dibuka, lakukan di post-frame callback denganWidgetsBinding.instance.addPostFrameCallback, bukan di initState.