Praktikum 3: Input Widgets dan Basic Form
Membuat form dasar, menerima, dan mengelola input dari pengguna di Flutter
PRAKTIKUM 3
Input Widgets dan Basic Form
1.1 Tujuan
Tujuan praktikum ini yaitu mahasiswa mampu membuat basic form untuk menerima inputan dari keyboard dan mengelola inputan:
- Membuat beberapa input widgets.
- Membuat dan mengontrol inputan dari user.
1.2 Alat
- Computer/laptop yang telah terinstall lingkungan flutter development.
1.3 Teori
TextField
Widget dasar untuk menerima input teks dari keyboard.
TextFormField
Versi lengkap dari TextField yang secara otomatis terintegrasi dengan logika validasi dan manajemen state dari sebuah Form.Fiturnya antara lain:
- Memiliki properti
validatoruntuk memeriksa input. - Menampilkan pesan error secara otomatis jika validasi gagal.
- Berinteraksi dengan
FormStateuntuk melakukan validasi kolektif.
GlobalKey<FormState>
GlobalKey merupakan objek unik yang digunakan untuk mengidentifikasi dan mengakses FormState.FormState adalah kelas yang mengelola status dari Form, seperti status validasi setiap field.Method validate() pada FormState digunakan untuk menjalankan validasi pada setiap TextFormField di dalam Form.
setState()
setState() adalah method yang memberitahu Flutter bahwa state internal dari sebuah StatefulWidget telah berubah, sehingga widget tersebut perlu di-render ulang (rebuild) untuk menampilkan perubahan.
Kata Kunci `const`
Kata kunci const pada widget digunakan untuk membuat widget menjadi konstanta pada saat kompilasi (compile-time).Penggunaan const dapat meningkatkan performa karena widget akan dibuat sekali dan disimpan di memori, sehingga dapat digunakan kembali tanpa perlu build ulang.
1.4 Langkah-langkah
Praktikum 1: Basic Form dengan TextField
1. Membuat Tampilan Awal
Buat file baru form_textfield.dart di dalam folder lib dan buat tampilan dasar form menggunakan kode berikut.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Basic Form'),
),
body: const MyForm(),
),
);
}
}
class MyForm extends StatefulWidget {
const MyForm({super.key});
@override
State createState() => _MyFormState();
}
class _MyFormState extends State {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Masukkan nama anda :'),
const SizedBox(height: 10),
const TextField(
decoration: InputDecoration(
labelText: 'Nama Lengkap',
hintText: 'Misalnya masnoer',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person)),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.amber, foregroundColor: Colors.black),
child: const Text('Tampilkan nama'),
)
],
),
);
}
} 2. Menambahkan TextEditingController
Pada class _MyFormState, tambahkan controller untuk mengambil dan membersihkan inputan.Controller berfungsi untuk mengambil inputan dari user.Method `dispose()` digunakan untuk membersihkan teks inputan.
final TextEditingController _textEditingController = TextEditingController();
@override
void dispose() {
_textEditingController.dispose();
super.dispose();
}3. Menghubungkan Controller ke TextField
Tambahkan property controller pada widget TextField untuk menghubungkannya dengan controller yang telah dibuat.
TextField(
controller: _textEditingController,
// ... properti lainnya
),
4. Menambahkan Aksi pada Tombol
Ubah method onPressed pada ElevatedButton untuk mengambil teks dari controller dan menampilkannya dalam sebuah SnackBar.
onPressed: () {
String inputText = _textEditingController.text;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Nama anda adalah, $inputText')),
);
},Praktikum 2: Basic Form dengan TextFormField
1. Membuat Tampilan Awal
Buat file baru form_textformfield.dart dan buat tampilan awal dengan dua TextFormField dan satu tombol.
2. Menambahkan State Management
Pada class state (misal: _MyFormTextState), tambahkan GlobalKey untuk form, controller untuk setiap field, dan method untuk submit.
final _formKey = GlobalKey();final _nameController = TextEditingController();final _emailController = TextEditingController();@override
void dispose() {_nameController.dispose();_emailController.dispose();super.dispose();}
void _submitForm() {if (_formKey.currentState!.validate()) {String name = _nameController.text;String email = _emailController.text;ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Validasi $name, $email Berhasil')),);
}
}
3. Menambahkan Form Key dan Validator
Bungkus Column dengan widget Form dan berikan _formKey.Kemudian, tambahkan properti validator pada setiap TextFormField.
TextFormField(
controller: _nameController,decoration: const InputDecoration(
labelText: "Nama", border: OutlineInputBorder()),validator: (value) {if (value == null || value.isEmpty) {return 'Masukkan nama anda';}
return null;},
),TextFormField untuk Email:
TextFormField(
controller: _emailController,decoration: const InputDecoration(
labelText: "Email", border: OutlineInputBorder()),validator: (value) {if (value == null || value.isEmpty) {return 'Masukkan email anda';}
if (!value.contains('@')) {return 'Email tidak valid';}
return null;},
),4. Menghubungkan Aksi Tombol
Panggil method _submitForm dari onPressed pada ElevatedButton.
ElevatedButton(
onPressed: _submitForm, child: const Text('Submit')
)
5. Kode Program Lengkap
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("Basic Form TextFormField"),
),
body: const MyFormText(),
),
);
}
}
class MyFormText extends StatefulWidget {
const MyFormText({super.key});
@override
State createState() => _MyFormTextState();
}
class _MyFormTextState extends State {
final _formKey = GlobalKey();
final _nameController = TextEditingController();
final _emailController = TextEditingController();
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
super.dispose();
}
void _submitForm() {
if (_formKey.currentState!.validate()) {
String name = _nameController.text;
String email = _emailController.text;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Validasi $name, $email Berhasil')),
);
}
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: "Nama", border: OutlineInputBorder()),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Masukkan nama anda';
}
return null;
},
),
const SizedBox(height: 10),
TextFormField(
controller: _emailController,
decoration: const InputDecoration(
labelText: "Email", border: OutlineInputBorder()),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Masukkan email anda';
}
if (!value.contains('@')) {
return 'Email tidak valid';
}
return null;
},
),
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _submitForm,
child: const Text('Submit'),
),
),
],
),
),
);
}
}
1.5 Latihan/Tugas
Pengerjaan Tugas Modul 3: Form Pendaftaran (Kelas B)
Sesuai dengan instruksi, dibuat sebuah form pendaftaran pengguna yang terdiri dari field nama, email, password, dan konfirmasi password.Aplikasi ini menggunakan `StatefulWidget` untuk mengelola input dan validasi pada setiap `TextFormField`.Validasi memastikan email mengandung format '@' dan password cocok dengan konfirmasi password.
Langkah Pengerjaan
- File `main.dart`: File ini berfungsi sebagai titik masuk aplikasi dan mengatur `MaterialApp` untuk memanggil halaman form pendaftaran.
-
File `user_registration_form.dart`: File ini berisi `StatefulWidget` utama.
- Menggunakan `GlobalKey
` untuk mengelola dan memvalidasi form. - Menggunakan `TextEditingController` untuk setiap input field, yang penting untuk membandingkan nilai password dan konfirmasi password.
- Menerapkan fungsi `validator` pada setiap `TextFormField` sesuai dengan persyaratan.
- Membuat method `_submitForm` yang akan dipanggil oleh tombol "Submit" untuk memicu validasi.
- Menggunakan `GlobalKey
Kode Program Lengkap
File: `main.dart`
import 'package:flutter/material.dart';
import 'user_registration_form.dart'; // Impor file form
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Form Pendaftaran',
theme: ThemeData(
primarySwatch: Colors.blue,
),
// Atur home ke widget form pendaftaran
home: const UserRegistrationForm(),
);
}
}
File: `user_registration_form.dart`
import 'package:flutter/material.dart';
// Gunakan StatefulWidget sesuai instruksi
class UserRegistrationForm extends StatefulWidget {
const UserRegistrationForm({super.key});
@override
State createState() => _UserRegistrationFormState();
}
class _UserRegistrationFormState extends State {
// GlobalKey untuk mengelola state Form
final _formKey = GlobalKey();
// Controller untuk setiap TextFormField
final _nameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _confirmPasswordController = TextEditingController();
@override
void dispose() {
// Bersihkan controller saat widget tidak lagi digunakan
_nameController.dispose();
_emailController.dispose();
_passwordController.dispose();
_confirmPasswordController.dispose();
super.dispose();
}
// Method yang dipanggil saat tombol ditekan
void _submitForm() {
// `validate()` akan memicu semua fungsi validator di dalam Form
if (_formKey.currentState!.validate()) {
// Jika semua validasi berhasil, tampilkan SnackBar
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Pendaftaran Berhasil!')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Form Pendaftaran Pengguna'),
),
body: Form(
key: _formKey, // Hubungkan GlobalKey dengan Form
child: SingleChildScrollView( // Agar bisa di-scroll jika layar kecil
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// TextFormField untuk Nama
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Nama Lengkap',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nama tidak boleh kosong';
}
return null;
},
),
const SizedBox(height: 16.0),
// TextFormField untuk Email
TextFormField(
controller: _emailController,
decoration: const InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email tidak boleh kosong';
}
// Validasi email harus mengandung format '@'
if (!value.contains('@')) {
return 'Format email tidak valid';
}
return null;
},
),
const SizedBox(height: 16.0),
// TextFormField untuk Password
TextFormField(
controller: _passwordController,
obscureText: true, // Sembunyikan teks password
decoration: const InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Password tidak boleh kosong';
}
if (value.length < 6) {
return 'Password minimal 6 karakter';
}
return null;
},
),
const SizedBox(height: 16.0),
// TextFormField untuk Konfirmasi Password
TextFormField(
controller: _confirmPasswordController,
obscureText: true,
decoration: const InputDecoration(
labelText: 'Konfirmasi Password',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Konfirmasi password tidak boleh kosong';
}
// Validasi password dan confirm password harus sama
if (value != _passwordController.text) {
return 'Password tidak cocok';
}
return null;
},
),
const SizedBox(height: 24.0),
// Tombol Submit
ElevatedButton(
// Panggil _submitForm saat tombol ditekan
onPressed: _submitForm,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16.0),
),
child: const Text('Submit'),
),
],
),
),
),
);
}
}