Laporan Praktikum 3 - Aplikasi Mobile
Input Widgets & Forms Menangkap Data, Dropdown, dan Validasi (Studi Kasus)
IF - Universitas Andalas
A. Pendahuluan
Pengelolaan formulir pada Flutter berpusat pada widget Form dan kunci pengendali GlobalKey
Dalam mengambil masukan berupa teks, digunakan widget TextFormField yang terintegrasi langsung dengan formulir dan dihubungkan ke TextEditingController. Pengendali ini bertugas membaca dan merekam setiap teks yang diketikkan oleh pengguna. Selain kolom teks, pengisian data pilihan juga dapat memanfaatkan DropdownButtonFormField untuk menyajikan opsi masukan terbatas dari daftar data statis.
Untuk menjaga integritas data, setiap kolom input dilengkapi dengan fungsi validator. Fungsi ini bertugas mengevaluasi masukan pengguna, di mana nilai balik berupa null menandakan bahwa data telah valid dan memenuhi kriteria. Sebaliknya, jika data tidak sesuai atau dibiarkan kosong, fungsi akan mengembalikan nilai berupa pesan kesalahan (string) yang otomatis ditampilkan di bawah kolom input.
B. Tujuan Praktikum
Adapun tujuan dari pelaksanaan praktikum ini adalah sebagai berikut::
- Menangkap teks dari pengguna via controller.
- Menerapkan widget dropdown statis.
- Validasi Input untuk Mencegah data kosong atau format salah.
C. Alat
Perangkat dan dependensi yang digunakan selama praktikum:
- Flutter SDK
- Code Editor : VS Code atau Android Studio.
- Emulator / Device
D. Langkah-langkah Praktikum
Praktikum diawali dengan membuat project baru dengan nama praktikum3 menggunakan Flutter.
Langkah pertama adalah membuat file baru bernama add_transaction_screen.dart. File ini digunakan untuk membuat halaman formulir pencatatan transaksi yang berisi input judul transaksi, nominal saldo, kategori, serta tombol untuk menyimpan data.
Kode dasar untuk membuat halaman adalah sebagai berikut.
Kode diatas mengimpor library material.dart yang menyediakan berbagai widget antarmuka Flutter. AddTransactionScreen dibuat sebagai StatefulWidget karena isi form dapat mengalami perubahan. Method createState() digunakan untuk menghubungkan widget dengan class _AddTransactionScreenState yang menangani seluruh state dan proses pada halaman form.
Selanjutnya dibuat class _AddTransactionScreenState yang berfungsi mengatur kondisi halaman. Pada bagian ini dibuat sebuah GlobalKey
_formKey digunakan untuk mengontrol Form, khususnya ketika proses validasi dijalankan. TextEditingController memungkinkan program mengambil teks yang diketik pengguna tanpa harus mengambil nilai secara manual dari widget. Sementara itu, _selectedCategory memiliki nilai awal Makanan, sehingga ketika form pertama kali dibuka kategori tersebut langsung menjadi pilihan aktif. List _categories berisi seluruh pilihan kategori yang nantinya ditampilkan dalam dropdown.
Setelah controller digunakan, controller perlu dibersihkan ketika halaman sudah tidak digunakan. Flutter menyediakan method dispose() untuk melakukan proses tersebut.
Method dispose() dipanggil ketika widget sudah dihapus dari widget tree. Pemanggilan dispose() pada masing-masing controller bertujuan melepaskan resource yang digunakan sehingga tidak terjadi penggunaan memori yang tidak diperlukan. Modul juga menjelaskan bahwa controller perlu dibersihkan ketika halaman ditutup untuk mencegah memory leak.
Setelah state siap, langkah berikutnya adalah membuat tampilan utama menggunakan Scaffold.
Scaffold digunakan sebagai struktur utama halaman Flutter. Pada bagian AppBar, ditampilkan judul “Catat Transaksi Baru” dengan warna latar ungu dan teks putih. Bagian body menggunakan SingleChildScrollView agar form tetap dapat digulir ketika keyboard muncul dan ukuran layar menjadi terbatas. Selanjutnya seluruh input dibungkus dengan widget Form dan dihubungkan dengan _formKey, sehingga setiap field di dalamnya dapat divalidasi secara bersamaan.
Input pertama digunakan untuk memasukkan judul transaksi.
Widget TextFormField digunakan karena selain menerima teks, widget ini juga memiliki fasilitas validasi melalui property validator. Controller _titleController digunakan untuk mengambil nilai yang dimasukkan pengguna. InputDecoration memberikan tampilan berupa label, garis tepi, dan ikon. Pada bagian validator, program memeriksa apakah nilai yang dimasukkan kosong. Jika kosong, validator mengembalikan pesan error sehingga Flutter menampilkan pesan tersebut pada form. Jika data sudah benar, validator mengembalikan null yang berarti tidak terdapat kesalahan.
Input kedua digunakan untuk memasukkan jumlah nominal transaksi.
Pada input nominal digunakan TextInputType.number sehingga keyboard yang ditampilkan lebih sesuai untuk memasukkan angka. Selain memeriksa apakah input kosong, validator juga menggunakan int.tryParse() untuk memastikan bahwa nilai yang diberikan benar-benar dapat dikonversi menjadi bilangan bulat. Jika proses konversi gagal, pengguna akan mendapatkan pesan bahwa nominal harus berupa angka yang valid. Dengan demikian, validasi tidak hanya memastikan data terisi, tetapi juga memastikan format data sesuai dengan kebutuhan.
Selanjutnya dibuat dropdown untuk memilih kategori transaksi.
DropdownButtonFormField digunakan untuk membuat pilihan kategori yang terintegrasi dengan form. Nilai awal dropdown diambil dari _selectedCategory, sedangkan items dibuat berdasarkan isi list _categories. Method map() digunakan untuk mengubah setiap data kategori menjadi DropdownMenuItem. Ketika pengguna memilih kategori lain, method onChanged dijalankan dan setState() digunakan agar nilai _selectedCategory diperbarui pada tampilan. Ada empat kategori, yaitu Makanan, Transportasi, Hiburan, dan Lainnya.
Bagian terakhir dari form adalah tombol untuk menyimpan transaksi sekaligus menjalankan validasi.
ElevatedButton digunakan sebagai tombol utama untuk menyimpan data. Pada onPressed, method _formKey.currentState!.validate() menjalankan seluruh fungsi validator yang terdapat di dalam Form. Jika seluruh input valid, program akan menampilkan SnackBar sebagai notifikasi bahwa transaksi berhasil disimpan. Data judul dan nominal diambil dari masing-masing controller dan ditampilkan di dalam pesan. Jika terdapat input yang tidak valid, proses penyimpanan tidak dilanjutkan dan pesan error akan ditampilkan pada field yang bermasalah.
Setelah halaman form selesai dibuat, langkah berikutnya adalah menghubungkan halaman tersebut dengan file utama main.dart agar dapat diakses pengguna.
Pada bagian awal, file add_transaction_screen.dart diimpor agar class AddTransactionScreen dapat digunakan. runApp() menjalankan aplikasi melalui class MyApp. MaterialApp digunakan sebagai konfigurasi utama aplikasi, termasuk judul dan tema warna. Sementara itu, property home diarahkan ke AddTransactionScreen, sehingga halaman formulir transaksi langsung ditampilkan ketika aplikasi dijalankan.
Setelah seluruh kode dibuat, aplikasi dijalankan melalui emulator atau device. Pengujian dilakukan dengan mencoba mengisi judul transaksi, nominal, dan memilih kategori. Kemudian tombol Simpan Transaksi ditekan untuk melihat apakah validasi berjalan sesuai dengan yang diharapkan. Jika seluruh data sesuai, aplikasi menampilkan SnackBar yang menunjukkan data transaksi yang berhasil diproses.
Pengujian juga dilakukan dengan sengaja membiarkan judul atau nominal kosong. Pada kondisi tersebut, validator akan menampilkan pesan kesalahan dan proses penyimpanan tidak dijalankan.
Selain itu, pengujian juga dilakukan dengan memasukkan nilai nominal yang bukan angka. Validator akan menampilkan pesan kesalahan bahwa nominal harus berupa angka yang valid.
Dengan demikian, seluruh mekanisme input, validasi, dan penyimpanan data dapat berjalan sesuai dengan yang diharapkan.
LATIHAN - Menambahkan Input Tanggal Transaksi
Pada latihan, ditambahkan satu input baru sebelum tombol Simpan untuk memasukkan Tanggal Transaksi. Modul menyediakan dua pendekatan, yaitu menggunakan TextFormField biasa dengan format DD/MM/YYYY atau menggunakan tombol yang menjalankan fungsi showDatePicker. Selain itu, input tanggal wajib memiliki validasi agar tidak boleh kosong.
Pada implementasi berikut digunakan pendekatan TextFormField yang dilengkapi showDatePicker. Cara ini membuat pengguna tidak perlu mengetik tanggal secara manual karena tanggal dapat dipilih melalui kalender.
Pertama, pada file add_transaction_screen.dart tambahkan controller baru pada class _AddTransactionScreenState.
Controller _dateController digunakan untuk menyimpan tanggal yang dipilih pengguna. Nilai tanggal yang dipilih melalui showDatePicker nantinya diubah menjadi format teks DD/MM/YYYY dan dimasukkan ke controller tersebut.
Menambahkan dispose() untuk Controller TanggalKarena telah menambahkan controller baru, controller tersebut juga harus dibersihkan ketika halaman ditutup.
Baris _dateController.dispose() berfungsi melepaskan resource yang digunakan oleh controller tanggal. Dengan demikian, seluruh controller yang dibuat di halaman tersebut dikelola dan dibersihkan dengan benar.
Menambahkan Input TanggalKemudian, tambahkan input tanggal di dalam widget form sebelum tombol Simpan.
TextFormField digunakan sebagai tempat untuk menampilkan tanggal yang telah dipilih. Property readOnly: true membuat pengguna tidak mengetik tanggal secara langsung, tetapi memilihnya melalui kalender. Ketika field ditekan, onTap dijalankan dan showDatePicker() menampilkan kalender. initialDate menggunakan tanggal saat ini sebagai pilihan awal, sedangkan firstDate dan lastDate menentukan rentang tanggal yang dapat dipilih.
Setelah pengguna memilih tanggal, hasilnya disimpan pada variabel pickedDate. Kondisi if (pickedDate != null) memastikan bahwa tanggal benar-benar dipilih sebelum dimasukkan ke controller. Nilai hari dan bulan menggunakan padLeft(2, '0') agar format selalu memiliki dua digit. Contohnya, tanggal 5 Januari 2026 akan ditampilkan sebagai 05/01/2026.
Validator pada input tanggal memeriksa apakah controller kosong. Jika kosong, validator mengembalikan pesan error "Tanggal transaksi wajib diisi." sehingga pengguna akan melihat pesan tersebut di bawah field. Jika tanggal sudah dipilih, validator mengembalikan null yang menandakan tidak ada kesalahan.
Hasil perubahan
Setelah kode latihan dijalankan, form memiliki tambahan field Tanggal Transaksi yang terletak setelah dropdown kategori dan sebelum tombol Simpan Transaksi.
Pengguna dapat menekan field tersebut untuk membuka kalender, kemudian memilih tanggal yang diinginkan. Tanggal yang dipilih akan ditampilkan dalam format DD/MM/YYYY.
Validasi tetap dilakukan ketika tombol Simpan Transaksi ditekan. Artinya, seluruh field pada form harus memenuhi aturan yang telah ditentukan. Judul transaksi dan nominal tidak boleh kosong, nominal harus berupa angka bulat, dan tanggal transaksi wajib dipilih.
Jika semua validasi berhasil, SnackBar menampilkan informasi transaksi beserta tanggal yang telah dipilih.
E. Kesimpulan
Berdasarkan praktikum yang telah dilaksanakan, dapat disimpulkan bahwa praktikum ini memberikan pemahaman mengenai penggunaan Input Widgets dan Forms pada Flutter untuk membangun formulir yang dapat menerima dan mengelola data dari pengguna. Melalui penggunaan TextFormField, DropdownButtonFormField, TextEditingController, dan GlobalKey, data seperti judul transaksi, nominal, dan kategori dapat ditangkap serta diproses dengan lebih terstruktur. Praktikum juga menunjukkan penerapan validasi menggunakan validator untuk memastikan data yang dimasukkan tidak kosong dan memiliki format yang sesuai sebelum diproses.
Pada latihan, formulir dikembangkan dengan menambahkan input Tanggal Transaksi menggunakan showDatePicker. Penambahan ini membuat proses pengisian tanggal lebih mudah sekaligus tetap dapat divalidasi agar wajib diisi. Secara keseluruhan, praktikum ini menunjukkan bahwa Flutter menyediakan widget dan mekanisme yang cukup lengkap untuk membangun form interaktif, menangkap input pengguna, mengatur pilihan data, serta melakukan validasi sehingga data yang diproses menjadi lebih terstruktur dan sesuai kebutuhan aplikasi.