Praktikum 1: TextField dan TextFormField
A. Pendahuluan
Flutter merupakan framework modern untuk pengembangan aplikasi mobile yang menawarkan beragam widget guna membangun antarmuka pengguna yang dinamis dan responsif. Salah satu elemen kunci dalam pengembangan aplikasi adalah kemampuan untuk menangani, mengelola, dan memvalidasi masukan dari pengguna. Dalam konteks ini, Flutter menyediakan dua widget utama untuk input teks: TextField dan TextFormField. TextField adalah widget dasar yang menawarkan fleksibilitas tinggi dalam hal tampilan dan perilaku, sehingga ideal untuk kasus penggunaan sederhana seperti bilah pencarian atau input tunggal. Di sisi lain, TextFormField adalah versi yang lebih canggih yang terintegrasi dengan widget Form dan dilengkapi fitur validasi kuat melalui properti validator. Hal ini memungkinkan pengembang untuk menetapkan aturan validasi secara deklaratif serta menampilkan pesan kesalahan secara otomatis.
Dalam sesi praktikum ini, dilakukan implementasi kedua widget input tersebut untuk memahami perbedaan karakteristik dan skenario penggunaannya. Implementasi mencakup pembuatan formulir dasar menggunakan TextField dengan TextEditingController untuk menangkap masukan pengguna dan memberikan umpan balik melalui SnackBar. Selain itu, dilakukan juga implementasi formulir dengan TextFormField yang dilengkapi mekanisme validasi menggunakan GlobalKey untuk memastikan data yang dimasukkan sesuai dengan aturan yang ditetapkan. Praktikum ini juga membahas konsep-konsep penting seperti StatefulWidget untuk pengelolaan state, metode lifecycle dispose() untuk membersihkan resource dan mencegah kebocoran memori, serta penggunaan kata kunci const untuk optimasi kinerja. Melalui praktikum ini, diharapkan pemahaman komprehensif dapat dicapai mengenai cara kerja widget input di Flutter, pengelolaan state dan controller, validasi masukan, serta penerapan praktik terbaik dalam mengembangkan formulir yang ramah pengguna dan berkinerja tinggi.
B. Tujuan
- Menguasai pemahaman mengenai konsep dan perbedaan antara TextField serta TextFormField, serta mampu menerapkannya dalam pembuatan formulir dasar di Flutter untuk menangani dan mengelola masukan dari pengguna.
- Dapat memanfaatkan TextEditingController untuk mengendalikan nilai input, GlobalKey untuk pengelolaan state formulir secara menyeluruh, serta mengimplementasikan metode validator guna melakukan validasi masukan berdasarkan aturan yang telah ditetapkan (seperti kolom wajib diisi dan format email).
- Memahami dan mengaplikasikan metode lifecycle dispose() untuk membersihkan resource dan menghindari kebocoran memori, sekaligus menggunakan setState() untuk memicu pembaruan tampilan widget saat terjadi perubahan pada state.
- Mampu menyediakan umpan balik kepada pengguna melalui SnackBar serta menerapkan praktik terbaik dalam pengembangan formulir yang mudah digunakan, berkinerja optimal, dan mengikuti prinsip clean code.
C. Langkah Pengerjaan
a. Praktikum
Implementasi Basic Form dengan TextField (form-textfield.dart)
1) Import Package Material
Pertama-tama, buat file baru bernama form-textfield.dart di dalam folder lib, lalu import package Flutter Material Design yang menyediakan berbagai widget dasar untuk membangun tampilan antarmuka.

2) Buat Class MyApp sebagai Widget Utama
Setelah itu, buat class MyApp sebagai widget utama yang menggunakan StatelessWidget karena tidak butuh perubahan state. Widget ini akan mengembalikan MaterialApp dengan Scaffold yang berisi AppBar dan body.

3) Buat Class MyForm sebagai StatefulWidget
Lalu, buat class MyForm yang extends StatefulWidget karena form ini akan menangani state berupa input teks dari pengguna. StatefulWidget memerlukan class State terpisah untuk mengurus logika dan state-nya.

4) Deklarasikan TextEditingController
Di dalam class _MyFormState, deklarasikan variabel _textEditingController yang berfungsi sebagai controller untuk mengambil dan mengelola nilai input dari TextField. Controller ini penting banget untuk menangkap nilai yang dimasukkan pengguna.

5) Override Method dispose()
Method dispose() dioverride untuk membersihkan TextEditingController saat widget dihapus dari widget tree. Ini penting untuk menghindari memory leak karena controller harus di-dispose secara manual.

6) Buat Layout dengan Padding dan Column
Pada method build(), buat layout menggunakan Padding untuk memberi jarak dari tepi layar, dan Column untuk menyusun widget secara vertikal dengan crossAxisAlignment.start agar konten rata kiri.

7) Tambahkan Widget Text sebagai Label
Tambahkan widget Text sebagai label instruksi buat pengguna, lalu ikuti dengan SizedBox untuk memberi jarak vertikal sebesar 10 pixel sebelum TextField.

8) Buat TextField dengan Decoration
Buat widget TextField dengan berbagai properti decoration biar tampilannya menarik. InputDecoration berisi labelText sebagai label, hintText sebagai placeholder, border: OutlineInputBorder() untuk border kotak, dan prefixIcon untuk ikon di sebelah kiri.

9) Tambahkan Controller dan Event Listener
Pada TextField yang sama, tambahkan properti controller yang terhubung ke _textEditingController, keyboardType untuk menentukan jenis keyboard yang muncul (text), dan onChanged sebagai event listener yang bakal jalan setiap kali ada perubahan input.

10) Tambahkan SizedBox untuk Jarak
Tambahkan SizedBox dengan height 20 untuk memberi jarak antara TextField dan tombol.

11) Buat ElevatedButton dengan SnackBar
Buat ElevatedButton dengan method onPressed yang akan mengambil nilai dari controller, lalu tampilkan nilai tersebut pakai SnackBar. Tombol ini juga diberi styling menggunakan styleFrom dengan background amber dan foreground hitam.

12) Jalankan Program
Terakhir, jalankan programnya dan lihat hasilnya.

Implementasi Form Validation dengan TextFormField (form-textformfield.dart)
1) Import Package dan Main Function
Sama kayak file sebelumnya, langkah awalnya yaitu import package Material dan bikin main function buat ngejalanin aplikasinya.

2) Buat Class MyApp dengan Judul Berbeda
Bikin class MyApp sebagai widget utama dengan judul AppBar "Basic Form TextFormField" biar beda dari implementasi TextField tadi.

3) Buat Class MyFormText sebagai StatefulWidget
Lalu buat class MyFormText yang extends StatefulWidget karena form ini bakal ngurus state yang lebih ribet pakai mekanisme validasi.

4) Deklarasikan GlobalKey dan Controller
Di dalam class _MyFormTextState, deklarasikan _formKey bertipe GlobalKey<FormState> yang gunanya buat akses state dari Form dan panggil method validasi. Terus deklarasikan juga dua controller buat field nama dan email.

5) Override Method dispose()
Method dispose() dioverride buat bersihin kedua controller (nama dan email) pas widget dihapus dari widget tree.

6) Buat Method _submitForm()
Bikin method _submitForm() yang bakal dipanggil pas tombol submit ditekan. Method ini pakai _formKey.currentState!.validate() buat ngejalanin validasi di semua TextFormField. Kalo validasi sukses (balikin true), maka nilai dari kedua controller diambil dan ditampilin pake SnackBar.

7) Buat Widget Form dengan GlobalKey
Pada method build(), layout dibungkus pake widget Form dan dikasih key _formKey buat nyambungin ke GlobalKey yang udah dideklarasikan. Form ini isinya Padding dan Column buat layout.

8) Buat TextFormField Pertama untuk Nama
Bikin TextFormField pertama buat input nama pake controller _nameController dan decoration yang sesuai. Yang bikin beda dari TextField yaitu adanya properti validator yang isinya logika validasi. Validator ini nerima parameter value dan balikin String kalo ada error, atau null kalo valid.

9) Tambahkan SizedBox untuk Jarak
Tambahin SizedBox buat jarak antar TextFormField.

10) Buat TextFormField Kedua untuk Email
Bikin TextFormField kedua buat input email pake controller _emailController. Validator di field ini lebih ribet karena ngecek dua kondisi: apakah field kosong dan apakah format email valid (ada '@').

11) Tambahkan SizedBox Sebelum Tombol
Tambahin SizedBox buat jarak sebelum tombol submit.

12) Buat Tombol Submit
Bikin SizedBox dengan width double.infinity biar tombolnya memenuhi lebar layar, terus di dalamnya ada ElevatedButton yang onPressed-nya manggil method _submitForm yang udah dibuat tadi.

13) Jalankan Program
Jalanin dan hasilnya bakal kayak gini.

b. Tugas
File main.dart - Aplikasi Kalkulator
1) Import Package Flutter dan Buat Fungsi Main
Import package material dari Flutter yang berisi komponen UI Material Design, lalu buat fungsi main() sebagai entry point aplikasi.

2) Buat Class MyApp sebagai StatelessWidget
Selanjutnya, buat class MyApp yang merupakan widget root dari aplikasi. Class ini tidak memerlukan state yang berubah-ubah (stateless).

3) Buat Class CalculatorPage sebagai StatefulWidget
Kemudian, buat class CalculatorPage yang merupakan StatefulWidget karena akan ada data yang berubah input angka dan hasil kalkulasi.

4) Buat State Class dan Deklarasikan Variable
Lalu, buat class _CalculatorPageState yang berisi logic dan state dari kalkulator. Deklarasikan controller untuk TextField dan variable untuk menyimpan hasil.

5) Buat Fungsi _calculate untuk Operasi Matematika
Selanjutnya, buat fungsi _calculate yang menerima parameter operasi dan melakukan perhitungan sesuai operator yang dipilih.

6) Buat Fungsi dispose untuk Membersihkan Controller
Kemudian, override fungsi dispose() untuk membersihkan memory dari controller ketika widget dihapus.

7) Buat Method build untuk UI - Scaffold dan AppBar
Lalu, buat method build() yang mengembalikan tampilan UI. Mulai dengan Scaffold dan AppBar.

8) Buat Body dengan SingleChildScrollView dan Padding
Selanjutnya, buat body dengan SingleChildScrollView agar konten bisa di-scroll jika layar kecil, lalu tambahkan padding.

9) Buat TextField Pertama untuk Input Angka Pertama
Kemudian, buat TextField pertama dengan controller dan dekorasi yang sesuai.

10) Buat TextField Kedua untuk Input Angka Kedua
Lalu, buat TextField kedua dengan struktur yang sama.

11) Buat Row untuk Tombol-tombol Operasi
Selanjutnya, buat Row yang berisi 4 tombol untuk operasi tambah, kurang, kali, bagi.

12) Buat Tombol Tambah (+)
Kemudian, buat tombol pertama untuk operasi penjumlahan dengan warna hijau.

13) Buat Tombol Kurang (-)
Lalu, buat tombol kedua untuk operasi pengurangan dengan warna orange.

14) Buat Tombol Kali (×)
Selanjutnya, buat tombol ketiga untuk operasi perkalian dengan warna biru.

15) Buat Tombol Bagi (÷)
Kemudian, buat tombol keempat untuk operasi pembagian dengan warna merah.

16) Buat Card untuk Menampilkan Hasil Kalkulasi
Lalu, buat Card dengan elevation untuk menampilkan hasil perhitungan dengan tampilan yang menarik.

17) Buat Tombol Clear untuk Reset Semua Input
Terakhir, buat tombol Clear untuk mengosongkan semua TextField dan mereset hasil ke nilai awal.

18) Jalankan Program dan Lihat Hasilnya
Jalankan codenya lalu hasilnya akan seperti dibawah ini. Aplikasi kalkulator dapat melakukan operasi penjumlahan, pengurangan, perkalian, dan pembagian dengan tampilan yang menarik.





D. Kesimpulan
Berdasarkan praktikum yang sudah dikerjakan, bisa disimpulkan bahwa Flutter menawarkan dua widget utama buat menangani input teks dari pengguna, yaitu TextField dan TextFormField. Keduanya punya karakteristik dan skenario pemakaian yang berbeda. TextField adalah widget yang lebih simpel dan fleksibel, cocok dipakai buat input tunggal atau form sederhana yang nggak butuh validasi ribet. Widget ini mengandalkan TextEditingController buat ngatur nilai input dan event listener onChanged buat nangkep perubahan secara real-time. Di sisi lain, TextFormField adalah widget yang lebih canggih dengan fitur validasi bawaan lewat properti validator. Widget ini terintegrasi dengan widget Form dan GlobalKey buat melakukan validasi kolektif terhadap beberapa input field, nampilin pesan error secara otomatis, serta ngelola state form secara terpusat pakai method validate().
Praktikum ini juga ngasih pemahaman mendalam soal konsep-konsep penting di Flutter, seperti penggunaan StatefulWidget buat ngurus state yang bisa berubah, TextEditingController buat ngontrol dan ambil nilai input, lifecycle method dispose() yang sangat penting buat bersihin resource dan menghindari memory leak, serta penggunaan setState() buat memicu rebuild widget pas ada perubahan state. Implementasi kedua jenis form ini nunjukin bahwa pemilihan widget yang tepat sangat tergantung pada tingkat kerumitan kebutuhan aplikasi. TextField cocok buat kasus sederhana dengan kontrol manual, sementara TextFormField lebih efisien buat form yang butuh validasi kompleks dengan banyak field. Penerapan best practice seperti penggunaan kata kunci const buat optimasi performa, pengelolaan resource yang baik dengan dispose(), dan pemberian feedback yang jelas ke pengguna lewat SnackBar merupakan hal fundamental yang wajib diperhatikan dalam pengembangan aplikasi Flutter yang handal, mudah dipakai, dan berkinerja optimal.
