Widget Input dan Validasi Form pada Flutter

Praktikum Aplikasi Mobile

Aplikasi Mobile
1. Pendahuluan

Flutter merupakan salah satu framework modern yang digunakan untuk mengembangkan aplikasi mobile. Framework ini menyediakan berbagai macam widget yang dapat digunakan untuk membuat antarmuka pengguna yang dinamis dan responsif. Dalam pengembangan aplikasi, salah satu hal yang penting adalah bagaimana aplikasi dapat menerima, mengelola, serta melakukan validasi terhadap input yang diberikan oleh pengguna. Untuk kebutuhan input teks, Flutter menyediakan dua widget yang umum digunakan, yaitu TextField dan TextFormField. TextField merupakan widget dasar yang memiliki fleksibilitas dalam mengatur tampilan maupun perilakunya, sehingga cocok digunakan pada kebutuhan sederhana seperti fitur pencarian atau input teks tunggal. Sementara itu, TextFormField memiliki fitur yang lebih lengkap karena dapat digunakan bersama widget Form dan mendukung proses validasi melalui properti validator, sehingga aturan validasi dapat ditentukan secara langsung dan pesan kesalahan dapat ditampilkan ketika input yang diberikan tidak sesuai.

Pada praktikum ini, kedua widget tersebut diimplementasikan untuk memahami karakteristik serta penggunaan masing-masing widget. Implementasi pertama dilakukan dengan membuat formulir sederhana menggunakan TextField dan TextEditingController untuk menerima serta mengelola input pengguna, kemudian memberikan informasi atau umpan balik melalui SnackBar. Selanjutnya, dilakukan pembuatan formulir menggunakan TextFormField yang dilengkapi dengan proses validasi. Pada bagian ini, GlobalKey digunakan untuk membantu memastikan bahwa data yang dimasukkan telah memenuhi aturan yang ditentukan. Selain membahas widget input, praktikum juga mencakup beberapa konsep pendukung, seperti penggunaan StatefulWidget dalam mengelola state, penerapan metode dispose() untuk membersihkan resource agar tidak terjadi kebocoran memori, serta penggunaan kata kunci const sebagai salah satu upaya optimasi kinerja aplikasi. Melalui praktikum ini, diharapkan dapat diperoleh pemahaman mengenai penggunaan widget input pada Flutter, pengelolaan state dan controller, proses validasi input, serta penerapan praktik yang tepat dalam membuat formulir yang mudah digunakan dan memiliki kinerja yang baik.

2. Tujuan
  • Memahami konsep dasar serta perbedaan antara widget TextField dan TextFormField, kemudian mampu menerapkannya dalam pembuatan formulir sederhana pada Flutter untuk menerima dan mengelola input dari pengguna.
  • Mampu menggunakan TextEditingController untuk mengatur nilai masukan, memanfaatkan GlobalKey dalam pengelolaan state formulir secara menyeluruh, serta mengimplementasikan metode validator untuk memvalidasi data berdasarkan aturan tertentu, seperti kolom yang wajib diisi dan format email yang benar.
  • Memahami serta menerapkan metode lifecycle dispose() untuk membersihkan resource sehingga dapat mencegah terjadinya kebocoran memori, sekaligus menggunakan setState() untuk memperbarui tampilan widget ketika terjadi perubahan pada state.
  • Mampu memberikan umpan balik kepada pengguna melalui SnackBar dan menerapkan praktik yang baik dalam pengembangan formulir agar mudah digunakan, memiliki performa yang optimal, serta sesuai dengan prinsip clean code.
3. Langkah Pengerjaan

Langkah pengerjaan terbagi menjadi dua bagian. Bagian pertama adalah praktikum, yang terdiri dari implementasi basic form menggunakan TextField dan implementasi form validation menggunakan TextFormField. Bagian kedua adalah tugas berupa pembuatan aplikasi kalkulator Kabataku. Setiap tahapan disertai screenshot potongan kode dan hasil tampilan aplikasi.

3.1 Praktikum: Implementasi Basic Form dengan TextField (form-textfield.dart)
  1. Membuat file baru bernama form-textfield.dart di dalam folder lib. Selanjutnya, melakukan import package Flutter Material Design yang menyediakan berbagai widget dasar untuk membangun antarmuka aplikasi.
    Membuat file form-textfield.dart dan import package Material
    Gambar 1. Membuat file form-textfield.dart dan import package Material.
  2. Membuat class MyApp sebagai widget utama dengan menggunakan StatelessWidget, karena pada bagian ini tidak terdapat perubahan state. Class tersebut akan mengembalikan MaterialApp yang di dalamnya terdapat Scaffold dengan komponen AppBar dan body.
    Class MyApp sebagai widget utama dengan MaterialApp dan Scaffold
    Gambar 2. Class MyApp sebagai widget utama dengan MaterialApp dan Scaffold.
  3. Membuat class MyForm yang merupakan turunan dari StatefulWidget karena formulir akan mengelola state berupa input teks dari pengguna. Penggunaan StatefulWidget membutuhkan class State terpisah yang bertugas mengatur state dan logika dari formulir tersebut.
    Class MyForm sebagai turunan StatefulWidget
    Gambar 3. Class MyForm sebagai turunan StatefulWidget.
  4. Pada class _MyFormState, mendeklarasikan variabel _textEditingController yang digunakan sebagai controller untuk mengambil dan mengelola nilai yang dimasukkan melalui TextField. Controller ini berperan penting dalam memperoleh data input dari pengguna.
    Deklarasi _textEditingController pada class _MyFormState
    Gambar 4. Deklarasi _textEditingController pada class _MyFormState.
  5. Melakukan override pada method dispose() untuk membersihkan textEditingController ketika widget sudah tidak digunakan atau dihapus dari widget tree. Langkah ini diperlukan untuk mencegah terjadinya memory leak, karena controller perlu dihentikan secara manual.
    Override method dispose() untuk membersihkan controller
    Gambar 5. Override method dispose() untuk membersihkan controller.
  6. Pada method build(), membuat struktur tampilan menggunakan Padding untuk memberikan jarak antara konten dengan tepi layar. Kemudian menggunakan Column untuk menyusun beberapa widget secara vertikal dengan crossAxisAlignment.start agar seluruh konten berada dalam posisi rata kiri.
    Struktur build() dengan Padding dan Column
    Gambar 6. Struktur build() dengan Padding dan Column.
  7. Menambahkan widget Text yang berfungsi sebagai label atau instruksi bagi pengguna. Setelahnya, menambahkan SizedBox untuk memberikan jarak vertikal sebesar 10 pixel sebelum komponen TextField.
    Widget Text sebagai label dan SizedBox sebagai jarak vertikal
    Gambar 7. Widget Text sebagai label dan SizedBox sebagai jarak vertikal.
  8. Membuat widget TextField dan mengatur beberapa properti decoration agar tampilannya lebih informatif. InputDecoration digunakan dengan beberapa properti, yaitu labelText sebagai label, hintText sebagai placeholder, border: OutlineInputBorder() untuk memberikan bentuk border kotak, serta prefixIcon untuk menampilkan ikon pada bagian kiri input.
    Widget TextField dengan pengaturan InputDecoration
    Gambar 8. Widget TextField dengan pengaturan InputDecoration.
  9. Pada TextField tersebut, menambahkan properti controller yang dihubungkan dengan _textEditingController. Selain itu, menggunakan keyboardType untuk menentukan jenis keyboard yang ditampilkan, yaitu tipe text, serta onChanged sebagai event listener yang akan dijalankan setiap kali terjadi perubahan pada input.
    Properti controller, keyboardType, dan onChanged pada TextField
    Gambar 9. Properti controller, keyboardType, dan onChanged pada TextField.
  10. Menambahkan kembali SizedBox dengan nilai height 20 untuk memberikan jarak antara TextField dengan tombol yang akan dibuat setelahnya.
    SizedBox sebagai jarak antara TextField dan tombol
    Gambar 10. SizedBox sebagai jarak antara TextField dan tombol.
  11. Membuat ElevatedButton dengan method onPressed yang berfungsi mengambil nilai input dari controller dan menampilkannya melalui SnackBar. Tombol tersebut juga diberikan pengaturan tampilan menggunakan styleFrom, dengan warna latar amber dan warna teks hitam.
    ElevatedButton dengan aksi menampilkan SnackBar
    Gambar 11. ElevatedButton dengan aksi menampilkan SnackBar.
  12. Setelah seluruh kode selesai dibuat, menjalankan program untuk melihat hasil implementasinya. Tampilan aplikasi yang dihasilkan dapat dilihat pada gambar berikut.
    Tampilan aplikasi basic form dengan TextField
    Gambar 12. Tampilan aplikasi basic form dengan TextField.
3.2 Praktikum: Implementasi Form Validation dengan TextFormField (form-textformfield.dart)
  1. Seperti pada file sebelumnya, mengimpor package Material dan membuat fungsi main() sebagai fungsi utama untuk menjalankan aplikasi.
    Import package Material dan fungsi main() pada form-textformfield.dart
    Gambar 13. Import package Material dan fungsi main() pada form-textformfield.dart.
  2. Membuat class MyApp sebagai widget utama. Pada bagian AppBar, menggunakan judul "Basic Form TextFormField" agar dapat membedakan implementasi ini dengan penggunaan TextField sebelumnya.
    Class MyApp dengan judul "Basic Form TextFormField"
    Gambar 14. Class MyApp dengan judul "Basic Form TextFormField".
  3. Membuat class MyFormText yang merupakan turunan dari StatefulWidget karena formulir yang dibuat akan mengelola state serta memiliki proses validasi terhadap input pengguna.
    Class MyFormText sebagai turunan StatefulWidget
    Gambar 15. Class MyFormText sebagai turunan StatefulWidget.
  4. Pada class _MyFormTextState, mendeklarasikan _formKey dengan tipe GlobalKey<FormState>. Variabel ini digunakan untuk mengakses state dari widget Form dan menjalankan proses validasi. Selain itu, membuat dua controller yang digunakan untuk mengelola input pada field nama dan email.
    Deklarasi _formKey dan controller nama serta email
    Gambar 16. Deklarasi _formKey dan controller nama serta email.
  5. Melakukan override pada method dispose() untuk membersihkan kedua controller, yaitu controller nama dan email, ketika widget sudah dihapus dari widget tree. Hal ini dilakukan agar resource yang digunakan dapat dilepaskan dengan baik.
    Override dispose() untuk membersihkan kedua controller
    Gambar 17. Override dispose() untuk membersihkan kedua controller.
  6. Membuat method _submitForm() yang akan dijalankan ketika tombol submit ditekan. Di dalam method tersebut, menggunakan _formKey.currentState!.validate() untuk menjalankan validasi pada seluruh TextFormField yang terdapat dalam Form. Jika proses validasi berhasil dan menghasilkan nilai true, maka nilai dari kedua controller akan diambil dan ditampilkan kepada pengguna melalui SnackBar.
    Method _submitForm() dengan proses validasi form
    Gambar 18. Method _submitForm() dengan proses validasi form.
  7. Pada method build(), membungkus layout menggunakan widget Form dan menghubungkannya dengan _formKey melalui properti key. Di dalam Form tersebut digunakan Padding dan Column untuk mengatur tata letak komponen formulir.
    Widget Form yang terhubung dengan _formKey
    Gambar 19. Widget Form yang terhubung dengan _formKey.
  8. Membuat TextFormField pertama yang digunakan sebagai input nama dengan menghubungkannya ke _nameController serta memberikan pengaturan decoration yang sesuai. Perbedaan utama dengan TextField sebelumnya adalah adanya properti validator yang digunakan untuk melakukan pemeriksaan terhadap input. Validator menerima nilai input sebagai parameter dan mengembalikan String apabila terdapat kesalahan atau null apabila input dinyatakan valid.
    TextFormField nama dengan properti validator
    Gambar 20. TextFormField nama dengan properti validator.
  9. Menambahkan SizedBox untuk memberikan jarak antara TextFormField pertama dengan field berikutnya sehingga tampilan formulir menjadi lebih rapi.
    SizedBox sebagai jarak antar field
    Gambar 21. SizedBox sebagai jarak antar field.
  10. Membuat TextFormField kedua untuk menerima input email menggunakan _emailController. Pada bagian validator, dilakukan pemeriksaan terhadap dua kondisi, yaitu memastikan field tidak kosong dan memeriksa apakah format email yang dimasukkan valid, salah satunya dengan memastikan terdapat karakter '@'.
    TextFormField email dengan validasi format email
    Gambar 22. TextFormField email dengan validasi format email.
  11. Menambahkan SizedBox kembali untuk memberikan jarak antara TextFormField dengan tombol submit.
    SizedBox sebagai jarak menuju tombol submit
    Gambar 23. SizedBox sebagai jarak menuju tombol submit.
  12. Membuat SizedBox dengan properti width: double.infinity agar tombol memiliki lebar yang mengikuti ukuran layar. Di dalam SizedBox tersebut, menambahkan ElevatedButton yang memiliki properti onPressed untuk memanggil method _submitForm() ketika tombol ditekan.
    ElevatedButton submit dengan lebar penuh layar
    Gambar 24. ElevatedButton submit dengan lebar penuh layar.
  13. Setelah seluruh implementasi selesai, menjalankan aplikasi untuk melihat hasil dari formulir yang telah dibuat.
    Tampilan aplikasi form validation dengan TextFormField
    Gambar 25. Tampilan aplikasi form validation dengan TextFormField.
3.3 Tugas: Aplikasi Kalkulator Kabataku (main.dart)

Pada bagian tugas, dibuat aplikasi kalkulator sederhana bernama Kabataku menggunakan framework Flutter. Aplikasi ini mengimplementasikan empat operasi matematika dasar, yaitu perkalian (kali), pembagian (bagi), penjumlahan (tambah), dan pengurangan (kurang). Aplikasi menampilkan dua TextField sebagai input angka, empat tombol operasi dengan warna berbeda, serta container untuk menampilkan hasil perhitungan.

  1. Melakukan import package dan setup awal aplikasi.
    Import package dan setup awal aplikasi
    Gambar 26. Import package dan setup awal aplikasi.
  2. Membuat widget utama (MyApp).
    Widget utama MyApp
    Gambar 27. Widget utama MyApp.
  3. Membuat halaman kalkulator (KalkulatorPage).
    Halaman kalkulator (KalkulatorPage)
    Gambar 28. Halaman kalkulator (KalkulatorPage).
  4. Membuat state management dan controller.
    State management dan controller
    Gambar 29. State management dan controller.
  5. Membuat fungsi perhitungan (kali, bagi, tambah, kurang).
    Fungsi perhitungan kali, bagi, tambah, dan kurang
    Gambar 30. Fungsi perhitungan kali, bagi, tambah, dan kurang.
  6. Membuat UI input fields.
    UI input fields
    Gambar 31. UI input fields.
  7. Membuat tombol operasi (4 tombol).
    Empat tombol operasi
    Gambar 32. Empat tombol operasi.
  8. Membuat display hasil.
    Display hasil perhitungan
    Gambar 33. Display hasil perhitungan.
  9. Membuat header aplikasi dengan icon dan deskripsi.
    Header aplikasi dengan icon dan deskripsi
    Gambar 34. Header aplikasi dengan icon dan deskripsi.
  10. Membuat dua TextField untuk input angka.
    Dua TextField untuk input angka
    Gambar 35. Dua TextField untuk input angka.
  11. Membuat grid 2x2 untuk 4 tombol operasi.
    Grid 2x2 untuk empat tombol operasi
    Gambar 36. Grid 2x2 untuk empat tombol operasi.
  12. Membuat container untuk menampilkan hasil.
    Container untuk menampilkan hasil
    Gambar 37. Container untuk menampilkan hasil.
  13. Melakukan dispose controller saat widget dihancurkan.
    Dispose controller saat widget dihancurkan
    Gambar 38. Dispose controller saat widget dihancurkan.
  14. Melakukan demonstrasi hasil aplikasi yang dijalankan melalui website (Flutter web).
    Demonstrasi tampilan awal aplikasi
    Gambar 39. Demonstrasi tampilan awal aplikasi.
    Hasil operasi kali
    Gambar 40. Hasil operasi kali.
    Hasil operasi bagi
    Gambar 41. Hasil operasi bagi.
    Hasil operasi tambah
    Gambar 42. Hasil operasi tambah.
    Hasil operasi kurang
    Gambar 43. Hasil operasi kurang.
4. Kesimpulan

Berdasarkan praktikum yang telah dilaksanakan, aplikasi Kalkulator Kabataku berhasil dibuat menggunakan framework Flutter dengan bahasa pemrograman Dart. Aplikasi ini mengimplementasikan empat operasi matematika dasar, yaitu perkalian (kali), pembagian (bagi), penjumlahan (tambah), dan pengurangan (kurang) yang disingkat menjadi "Kabataku". Dalam pengembangannya, aplikasi ini memanfaatkan konsep State Management melalui StatefulWidget untuk mengelola perubahan data secara dinamis, serta menggunakan TextEditingController untuk mengontrol input pengguna pada TextField. Aplikasi dirancang dengan antarmuka yang intuitif dan user-friendly, menampilkan dua TextField sebagai input angka pertama dan kedua, empat tombol operasi yang dibedakan dengan warna berbeda (kuning untuk perkalian, hijau untuk pembagian, biru untuk penjumlahan, dan merah untuk pengurangan) dalam layout GridView 2x2, serta hasil perhitungan ditampilkan dalam container dengan format yang jelas, misalnya "10 + 5 = 15".

Dari segi fungsionalitas, aplikasi dilengkapi dengan berbagai validasi input untuk meningkatkan user experience dan mencegah error, antara lain validasi input kosong, validasi format angka menggunakan FilteringTextInputFormatter yang membatasi input hanya berupa angka dan titik desimal, serta validasi khusus untuk operasi pembagian yang mencegah pembagian dengan angka nol. Selain itu, aplikasi juga menyediakan fitur reset melalui tombol refresh pada AppBar yang memungkinkan pengguna menghapus semua input dan hasil perhitungan sekaligus.

Secara keseluruhan, aplikasi Kalkulator Kabataku telah memenuhi seluruh requirement yang ditetapkan dalam tugas praktikum, yaitu penggunaan dua widget input (TextField) untuk menerima nilai inputan, implementasi ElevatedButton untuk mengeksekusi operasi perhitungan, serta penggunaan widget Text untuk menampilkan hasil operasi. Aplikasi ini juga menunjukkan penerapan prinsip-prinsip dasar pemrograman Flutter seperti widget tree, state management, event handling, serta styling dan theming menggunakan Material Design 3. Dengan demikian, praktikum ini memberikan pemahaman yang komprehensif mengenai pengembangan aplikasi mobile menggunakan Flutter, khususnya dalam membuat aplikasi kalkulator sederhana dengan multiple operations dan validasi input yang robust.