Kontrak Perkuliahan
2. Pengenalan HTTP & API
3. Tampil Data API Firebase
3.1 Menampilkan data API
Syarat : sudah terinstall flutter dan get_cli
Buat Projek baru dengan nama flutter_application_3_tampil lalu jalankan perintah get init untuk
menggunakan get pattern di flutter.
Pada latihan ini, kita akan mengambil data dari api dengan url berikut:
https://materi-flutter-default-rtdb.asia-southeast1.firebasedatabase.app/students.json
Untuk mengambil data dari API, kita perlu membuat file provider, file ini bertugas untuk melakukan
request ke url.
Setelah menjalankan perintah diatas, get_cli akan membuatkan kita file dengan nama student_provider
di \lib\app\data\student_provider.dart
Get_cli merupakan packages bagian dari getx, dengan get_cli kita dimudahkan untuk membuat file
dengan perintah-perintah di terminal.
Buka file student_provider.dart lalu kita buat kode untuk melakukan request seperti berikut:
import 'package:get/get.dart';
Perintah diatas, kita membuat fungsi/method dengan nama getAll, method getAll merupakan method
dengan tipe async, method ini mengembalikan future dynamic
Synchronous merupakan eksekusi yang dilaksanakan secara berurutan, jika terdapat ada 2 perintah,
perintah satu membutuhkan waktu 2 menit maka perintah kedua tidak akan di eksekusi sebelum
perintah satu selesai di eksekusi.
Kebalikan dari Synchronous, Asynchronous memungkinkan ekseksui perintah kedua tanpa harus
menunggu perintah pertama selesai.
Flutter menggunakan bahasa pemrograman dart, pada bahasa dart, untuk menjalankan asynchronous
pada sebuat method kita bisa menggunakan keyword async pada body method dan keyword
await pada perintah yang ingin di asynchronous lalu tipe kembalian method tersebut adalah
Future<tipe-data> seperti contoh berikut:
Future<Response<dynamic>> getAll() async {
return await get(
'https://materi-flutter-default-rtdb.asia-southeast1.firebasedatabase.app/students.json');
}
Buka file home_controller.dart lalu buat kode seperti berikut:
import 'package:flutter_application_3_tampil/app/data/student_provider.dart';
import 'package:get/get.dart';
@override
void onInit() {
StudentProvider().getAll().then((Response response) {
if (response.statusCode == 200) {
final Map<String, dynamic> jsonResponse = response.body;
jsonResponse.forEach((key, value) {
Map student = {
"nama": value['nama'],
"kelas": value['kelas'],
};
listData.add(student);
});
} else {
Get.snackbar('Error', response.statusText!);
}
});
super.onInit();
}
}
Di home_controller.dart, kita menggunakan method onInit, semua kode di method ini akan dieksekusi
pada saat controller dibuat di memory (sesaat sebelum view ditampilkan).
Untuk mendapatkan respon dari method asynchronous kita bisa menggunakan then seperti kode
diatas. Jadi pada saat kita memanggil method asynchronous, kita menambahkan method then dengan
menambahkan parameter tipe data dari respon method async.
StudentProvider().getAll().then((Response response) {
print(response);
});
Setelah mendapatkan respon dari http request get di student_provider.dart, berikutnya kita cek apakah
respon yang dilakukan berhasil melalui statusCode seperti berikut:
if (respon.statusCode == 200) {
final Map<String, dynamic> jsonResponse = response.body;
jsonResponse.forEach((key, value) {
Map student = {
"nama": value['nama'],
"kelas": value['kelas'],
};
listData.add(student);
});
} else {
Get.snackbar('Error', response.statusText!);
}
Jika statusCode tidak sama dengan 200, maka sistem akan menampilkan error di snackbar, jika berhasil
maka kita akan mengambil data dari http response body kemudian langsung mengubah datanya menjadi
tipe data Map seperti berikut:
final Map<String, dynamic> mapAllData = response.body;
Data yang di konvert dari respon.body ke map akan menjadi seperti array, maka kita bisa menggunakan
perulangan forEach untuk mengambil data satu persatu dan mengolah data tersebut seperti berikut:
final Map<String, dynamic> jsonResponse = response.body;
jsonResponse.forEach((key, value) {
Map student = {
"nama": value['nama'],
"kelas": value['kelas'],
};
listData.add(student);
});
Pada kode diatas, kita melakukan perulangan, lalu di setiap perulangan kita membuat objek map
dengan nama student, lalu objek tersebut kita tambahkan ke variable listData menggunakan
method add.
Pada kode diatas, kita mengatur background dari scaffold dengan argument
backgroundColor: Colors.white70,
Lalu kita menghitung jumlah data yang ada di listData dengan perintah:
itemCount: controller.listData.length,
Pada bagian perulangan itemBuilder kita membuat variabel baru dengan nama list, variabel ini akan
menampung setiap item dari listData sesuai index, misalnya di perulangan pertama, variabel list akan
berisi data objek {nama: budi, kelas: 01PS5} sesuai dengan data dari API lalu data yang ada di
variabel list ini ditampilkan di widget ListTile sesuai dengan key nya
Flutter menyediakan widget animasi loading yang bisa kita gunakan yaitu:
CircularProgressIndicator()
Buka file home_controller, kita akan menambahkan satu variabel boolean untuk menyimpan perubahan
status request seperti berikut:
import 'package:flutter_application_3_tampil/app/data/student_provider.dart';
import 'package:get/get.dart';
@override
void onInit() {
isLoading.value = true;
StudentProvider().getAll().then((Response response) {
if (response.statusCode == 200) {
final Map<String, dynamic> jsonResponse = response.body;
jsonResponse.forEach((key, value) {
Map student = {
"nama": value['nama'],
"kelas": value['kelas'],
};
listData.add(student);
});
} else {
Get.snackbar('Error', response.statusText!);
}
isLoading.value = false;
});
super.onInit();
}
}
Pada kode diatas, kita mengatur nilai isLoading menjadi true sebelum data student diambil,lalu
setelah perulangan forEach selesai, kita mengatur nilai isLoading menjadi false
Klik kanan pada ListView.builder lalu refactor dengan memilih wrap with widget modifikasi widget
menjadi obx agar semua widget di body dibungkus dengan Obx seperti berikut:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
return Container(
color: Colors.white,
margin: EdgeInsets.all(5),
child: ListTile(
title: Text(list['nama']),
subtitle: Text(list['kelas']),
),
);
},
),
));
}
}
Setelah melakukan wrap widget, berikutnya kita akan menampilkan circular progress indicator jika
isLoading bernilai true menggunakan tenary operator seperti berikut:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
return Container(
color: Colors.white,
margin: EdgeInsets.all(5),
child: ListTile(
title: Text(list['nama']),
subtitle: Text(list['kelas']),
),
);
},
),
),
);
}
}
Jika variabel isLoading bernilai true maka widget yang ditampilkan adalah widget Center yang memiliki
child CircularProgressIndicator, jika isLoading bernilai false maka menampilkan ListView.builder
3.3 Menggunakan Model Data
Untuk menghandle data API (URL), programmer biasanya membuat sebuah class model untuk
memudahkan dalam mengakses data tersebut, sebagai contoh, kita akan membuat class dengan nama
StudentModel untuk membuat class, klik kanan di folder lib\app\data lalu pilih new file seperti
gambar berikut:
Data[‘nama’]
Data.attribute
Kita bisa mengetik kode model secara manual atau menggunakan situs-situs untuk melakukan generate
model seperti https://app.quicktype.io/?l=dart . Dengan menggunakan situs ini, kita cukup memasukkan
respon json lalu model data akan di generate sendiri seperti berikut:
Klik make all properties required lalu copy kode diatas dan pastekan di bagian bawah file
home_controller.dart seperti berikut:
StudentModel studentModelFromJson(String str) =>
StudentModel.fromJson(json.decode(str));
class StudentModel {
StudentModel({
required this.createdAt,
required this.kelas,
required this.nama,
required this.nim,
});
String createdAt;
String kelas;
String nama;
String nim;
Pada class ini kita membuat beberapa properti dengan tipe data String. Tanda tanya ? pada string
mengindikasikan bahwa variabel ini bisa berisi string atau null.
Kita juga membuat Method dengan tipe factory untuk mengubah format data dari json menjadi model.
Jika data dari API ada yang bernilai null maka kita ubah menjad kosong, kita juga mengubah tipe data
nim menjadi string.
Selanjutnya kita akan mengubah kode di home_controller.dart menjadi seperti berikut :
import 'package:flutter_application_3_tampil/app/data/student_provider.dart';
import 'package:get/get.dart';
@override
void onInit() {
isLoading.value = true;
StudentProvider().getAll().then((Response response) {
if (respon.statusCode == 200) {
final Map<String, dynamic> jsonResponse = response.body;
jsonResponse.forEach((key, value) {
StudentModel studentModel = StudentModel.fromJson(value);
studentModel.key = key;
listData.add(studentModel);
});
} else {
Get.snackbar('Error', response.statusText!);
}
isLoading.value = false;
});
super.onInit();
}
}
Perubahan pertama dilakukan pada bagian definisi variabel listData, tipe data List diganti menjadi var,
variabel ini disiapkan untuk menyimpan data List dengan tipe StudentModel.
Variable listData ini juga di observer agar perubahan nilai di variabel ini bisa selalu diikuti oleh screen.
var listData = List<StudentModel>.empty().obs;
Pada perubahan kedua, kita membuat objek studentModel dari class StudentModel yang
menjalankan method fromJson(val). Method fromJson ini akan mengubah tipe data json yaitu val
menjadi objek StudentModel sehingga proses perubahan data tidak lagi di lakukan di class
HomeController tetapi dilakukan di class StudentModel
Buka home_view.dart, lalu modifikasi kode pada bagian berikut:
body: Obx(
() => controller.isLoading.value
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: controller.listData.length,
itemBuilder: (BuildContext context, int index) {
var list = controller.listData[index];
return Container(
color: Colors.white,
margin: EdgeInsets.all(5),
child: ListTile(
title: Text(list.nama),
subtitle: Text(list.kelas),
),
);
},
),
)
Pada file home_view, kita mengubah cara mengakses data list yang tadinya menggunakan array
Text(list['nama'])
Jika terdapat Tanda ! menyatakan bahwa kita memberitahu kepada flutter bhwa variabel ini tidak
akan null.
3.4 Membuat Method getStudents
Agar proses mengambil data dari API dapat dilakukan dengan mudah, kita bisa memindahkan kode di
onInit ke fungsi/method khusus sehingga dapat digunakan berkali-kali sesuai kebutuhan.
Buat method dengan nama getStudents() lalu pindahkan kode dari onInit sehingga kode di
home_controller menjadi seperti berikut:
import 'package:flutter_application_3_tampil/app/data/student_provider.dart';
import 'package:get/get.dart';
@override
void onInit() {
getStudents ();
super.onInit();
}
void getStudents() {
isLoading.value = true;
StudentProvider().getAll().then((Response respon) {
if (respon.statusCode == 200) {
final Map<String, dynamic> jsonResponse = respon.body;
jsonResponse.forEach((key, val) {
StudentModel studentModel = StudentModel.fromJson(val);
studentModel.key = key;
listData.add(studentModel);
});
} else {
Get.snackbar('Error', respon.statusText!);
}
isLoading.value = false;
});
}
}
Pada kode diatas, kita memindahkan semua kode untuk mengolah data dari provider dari onInit
ke method getStudents, lalu di method onInit kita memanggil method getData. Dengan cara seperti ini,
kita bisa memanggil method getStudents dari kode mana saja sesuai dengan kebutuhan.
4. Tampil Data reqres.in
Selain API firebase, kita juga bisa menggunakan publik API lainnya seperti yang ada di situs reqres.in
berikut URL:
https://reqres.in/api/users?page=2
1. page
2. per_page
3. total
4. total_pages
5. data
6. support
Pada key data terdapat data user dalam bentuk json array.
Kita akan melakukan request di API reqres dengan membuat file provider baru dengan nama
user_provider
Pada kode diatas, kita mengambil data sesuai dengan key datanya, misalnya key data yang berisi array
data user. Lalu ada key page, per_page dan data lainnya yang sesuai dengan kebutuhan kita.
Kita juga memodifikasi studentModel dengan key yang berbeda agar tidak perlu mengubah kode di
home_view, karena key yang ada di firebase dan di reqres berbeda seperti berikut:
Map studentModel = {
'nama': element['email'],
'kelas': element['first_name'],
};
5. Tambah Data
Buka project flutter_application_3_tampildata lalu jalankan di chrome.
Buka home_controller.dart lalu buat method dengan nama onTapButtonTambah seperti berikut:
void onTapButtonTambah() {
Get.toNamed(Routes.STUDENT_FORM);
}
Method onTapButtonTambah jika dijalankan akan membuka halaman STUDENT_FORM.
void addData() {
isLoading.value = true;
String nama = txtNama.text;
String kelas = txtKelas.text;
String nim = txtNim.text;
if (nama.isEmpty || kelas.isEmpty || nim.isEmpty) {
Get.snackbar(
"Error",
"Data tidak boleh kosong",
backgroundColor: Colors.red,
colorText: Colors.white,
);
isLoading.value = false;
return;
}
//buat data json
var studentJson = jsonEncode({
"created_at": DateTime.now().toString(),
"kelas": kelas,
"nama": nama,
"nim": int.parse(nim), //ini harus diubah menjadi integer
});
//kirim data ke provider
StudentProvider().postData(studentJson).then((value) {
if (value.statusCode == 200) {
Get.snackbar(
"Success",
"Data berhasil ditambahkan",
backgroundColor: Colors.green,
colorText: Colors.white,
);
} else {
Get.snackbar(
"Error",
value.statusText!,
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
isLoading.value = false;
});
}
}
Pada kode diatas, kita menyiapkan variabel dengan tipe TextEditingController yang nantinya akan
digunakan oleh widget TextField. Kita juga membuat variabel isLoading untuk menandai state apakah
sebelum request atau sesudah request.
Kita juga membuat method dengan nama addData() method ini akan memeriksa apakah nilai
TextEditingController kosong, jika kosong maka akan tampil pesan. Jika tidak maka eksekusi dilanjutkan
ke baris berikutnya.
Pada kode diatas, kita membuat data json yang berasal dari TextEditingController seperti berikut:
var studentJson = jsonEncode({
"created_at": DateTime.now().toString(),
"kelas": kelas,
"nama": nama,
"nim": int.parse(nim),
});
Variabel studentJson ini kita kirim ke postData yang ada di student_provider untuk kemudian di kirim ke
API firebase.
5.3 Buat Tampilan View
Selanjutkan kita mengubah student_form_view.dart menjadi seperti berikut:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/student_form_controller.dart';
6. Ubah Data
Untuk mengubah data API, kita membutuhkan attribute yang unik, pada api firebase kita bisa
menggunakan unik id seperti berikut:
Buka home_controller.dart lalu modif kode pada method getStudents seperti berikut:
jsonResponse.forEach((key, value) {
Map studentModel = {
"key":key,
"nim": value['nim'],
"nama": value['nama'],
"kelas": value['kelas'],
};
listData.add(studentModel);
});
Pad kode diatas, kita menambahkan data key dan nim ke studentModel, key ini yang nantinya akan
digunakan untuk mengubah data.
Berikutnya kita akan membuat method agar user berpindah ke page studentEditForm. Buka
home_controller.dart lalu tambahkan kode berikut:
void onTapButtonEdit(var studentModel) async {
var data =
await Get.toNamed(Routes.STUDENT_EDIT_FORM, arguments: studentModel);
if (data != null) {
getStudents();
}
}
Pada kode diatas, kita membuat kode untuk berpindah ke student edit dengan membawa data
argument yaitu studentmodel yang didapat dari parameter. Kita menggunakan await yang digunakan
ketika user kembali ke halaman ini maka method getStudents akan dijalankan.
return Container(
color: Colors.white,
margin: EdgeInsets.only(bottom: 1),
child: ListTile(
title: Text(list['nama']),
subtitle: Text(list['kelas']),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () => controller.onTapButtonEdit(list),
icon: Icon(Icons.edit),
)
],
),
),
);
Pada kode diatas, kita membuat icon button di argument trailing dan pada saat icon di tekan kita
memanggil method onTapButtonEdit(list), di onTapButtonEdit, kita mengirim parameter list yang berisi
nama, kelas dan key.
Buka student_edit_form_controller.dart lalu modifikasi kodenya menjadi seperti berikut:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_application_3_tampil/app/data/student_provider.dart';
import 'package:get/get.dart';
@override
void onInit() {
txtNama.text = studentModel['nama'];
txtNim.text = studentModel['nim'].toString();
txtKelas.text = studentModel['kelas'];
super.onInit();
}
void editData() {
isLoading.value = true;
String nama = txtNama.text;
String nim = txtNim.text;
String kelas = txtKelas.text;
if (nama.isEmpty || kelas.isEmpty || nim.isEmpty) {
Get.snackbar(
"Error",
"Data tidak boleh kosong",
backgroundColor: Colors.red,
colorText: Colors.white,
);
isLoading.value = false;
return;
}
StudentProvider()
.updateData(studentModel['key'], studentModelBaru)
.then((Response response) {
if (response.statusCode == 200) {
Get.defaultDialog(
title: "OK",
middleText: 'Data berhasil disimpan',
barrierDismissible: false,
onConfirm: () {
Get.back();
Get.back(result: true);
});
} else {
Get.snackbar(
"Error",
response.statusText!,
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
isLoading.value = false;
});
}
}
Pada kode diatas, kita mengambil nilai yang dikirim dari onTapButtonEdit dengan perintah
var studentModel = Get.arguments;
lalu pada method onInit, kita mengisi nilai di variabel TextEditingController txtNama, txtNim, txtKelas:
@override
void onInit() {
txtNama.text = studentModel['nama'];
txtNim.text = studentModel['nim'].toString();
txtKelas.text = studentModel['kelas'];
super.onInit();
}
Kode ini untuk menampilkan nilai di widget TextField
Pada kode ini, kita menggunakan Get.defaultDialog untuk menampilkan konfirmasi data berhasil
disimpan. Jika user mengklik tombol ok, maka kita menjalankan Get.back() untuk menutup dialog lalu
kita menjalankan lagi Get.back(‘result:true’) untuk kembali ke halaman sebelumnya dengan membawa
data result true.
Buka file home_student_ edit_form.dart lalu modif seperti berikut: (kode ini sama dgn kode
student_form.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/student_edit_form_controller.dart';
7. Hapus Data
Buka file student_provider.dart lau tambahkan method berikut:
Future<Response<dynamic>> deleteData(String id) async {
return await delete(
"https://materi-flutter-default-rtdb.asia-southeast1.firebasedatabase.app/students/$id.json");
}
Buka home_controller.dart lalu tambahkan method berikut:
Selanjutnya kita akan membuat icon delete di listtile, buka home_view.dart lalu modifikasi kodenya jadi
seperti berikut:
return Container(
color: Colors.white,
margin: EdgeInsets.only(bottom: 1),
child: ListTile(
title: Text(list['nama']),
subtitle: Text(list['kelas']),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () => controller.onTapButtonEdit(list),
icon: Icon(Icons.edit),
),
IconButton(
onPressed: () =>
controller.onTapIconDelete(list['key']),
icon: Icon(Icons.delete),
),
],
),
),
Pada onPressed icon delete, kita memanggil fungsi onTapIconDelete dengan membawa nilai dari key.
Key inilah nanti yang akan dikirim ke provider lalu di kirim ke API firebase untuk dihapus.
8. MID
9. Proyek Aplikasi SPP
Pada bagian ini kita akan membuat proyek baru, kita akan membuat aplikasi yang terdiri dari modul:
1. Register
2. Login
3. Home (auth)
4. Data siswa (auth)
5. Data Biaya (auth)
6. Data Tagihan (auth)
Setiap proses request harus menambahkan pada bagian http header yaitu Accept: application/json
Untuk mengakses modul selain register dan login, kita harus menambahkan pada bagian http header
berupa bearer token yang didapat dari proses login.
10. Register
Membuat Register sama dengan membuat tambah data, karena register adalah proses user mengirim
data ke server.
Jika pendaftaran berhasil, maka sistem belajar-api unama akan mengirim email untuk mengaktifkan
akun agar dapat login.
Buat Proyek baru dengan nama flutter_proyek_nim lalu jalankan perintah get init:
get init
Install package flutter_easy_loading agar kita bisa dengan mudah membuat loading
(https://pub.dev/packages/flutter_easyloading ) :
flutter pub add flutter_easyloading
Buka file app_pages.dart di file ini kita akan mengubah inisial page, sehingga page yang akan dijalankan
pertama kali adalah page register
static const INITIAL = Routes.REGISTER;
simpan lalu lakukan reload.
void onTapButtonSimpan() {
String name = txtName.text;
String email = txtEmail.text;
String password = txtPassword.text;
if (name.isEmpty || email.isEmpty || password.isEmpty) {
Get.snackbar(
"Proses Gagal",
'Data tidak boleh kosong',
backgroundColor: Colors.red,
colorText: Colors.white,
);
return;
}
EasyLoading.show();
var dataRegistrasi = {
"name": name,
"email": email,
"password": password,
};
RegisterProvider().postData(dataRegistrasi).then((Response response) {
var responseBody = response.body;
EasyLoading.dismiss();
if (response.statusCode == 201) {
Get.snackbar(
"Success",
"Data berhasil ditambahkan",
backgroundColor: Colors.green,
colorText: Colors.white,
);
txtName.text = "";
txtEmail.text = "";
txtPassword.text = "";
} else if (response.statusCode == 422) {
Get.snackbar(
"Proses Gagal",
responseBody['message']!,
backgroundColor: Colors.red,
colorText: Colors.white,
);
} else {
Get.snackbar(
"Proses Gagal",
"Terjadi Kesaahan ",
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
});
}
void onTapTextLogin() {
Get.toNamed(Routes.LOGIN);
}
}
Install package baru dengan nama sp_util, dengan package ini kita dapat menyimpan token dan data
user secar persistent.
flutter pub add sp_util
Reload aplikasi.
Buka file main.dart lalu modif fungsi main untuk menjalankan package sp_util :
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SpUtil.getInstance();
runApp(
GetMaterialApp(
title: "Application",
initialRoute: AppPages.INITIAL,
getPages: AppPages.routes,
debugShowCheckedModeBanner: false,
builder: EasyLoading.init(),
),
);
}
Buka file register_view.dart lalu tambahkan kode untuk mengarahkan user ke halaman Login
void onTapButtonLogin() {
String email = txtEmail.text;
String password = txtPassword.text;
if (email.isEmpty || password.isEmpty) {
Get.snackbar(
"Proses Gagal",
'Data tidak boleh kosong',
backgroundColor: Colors.red,
colorText: Colors.white,
);
return;
}
EasyLoading.show();
var dataLogin = {
"email": email,
"password": password,
};
UserProvider().login(dataLogin).then((Response response) {
var responseBody = response.body;
EasyLoading.dismiss();
if (response.statusCode == 200) {
var responseData = responseBody['data'];
SpUtil.putString('token', responseData['token']);
SpUtil.putString('id', responseData['id'].toString());
SpUtil.putString('name', responseData['name']);
SpUtil.putString('email', responseData['email']);
SpUtil.putBool('isLogin', true);
Get.offAllNamed(Routes.HOME);
} else if (response.statusCode == 422) {
Get.snackbar(
"Proses Gagal",
responseBody['message']!,
backgroundColor: Colors.red,
colorText: Colors.white,
);
} else {
Get.snackbar(
"Proses Gagal",
"Terjadi Kesaahan ",
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
});
}
}
Pada kode login, jika login berhasil maka kita menggunakan perintah Get.offAllNamed perintah ini akan
mengarahkan user ke halaman home dan user tidak bisa kembalil ke halaman sebelumnya.
Pada halaman utama diatas terdapat tombol untuk mengubah profil, mengolah data siswa dan tombol
logout. Kita akan membuat page untuk ubah profil dan mengolah data siswa.
get create page:ProfilForm
@override
Widget build(BuildContext context) {
double widthButton = Get.width - 130;
return Scaffold(
appBar: AppBar(
title: const Text('Halaman Utama'),
backgroundColor: Colors.white,
elevation: 0,
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(top: Get.height / 5),
child: Text(
'Aplikasi Tagihan SPP',
style: TextStyle(fontSize: 20),
),
),
Container(
margin: EdgeInsets.only(top: 0),
child: Text(
'SD Usaha Mandiri',
style: TextStyle(fontSize: 30),
),
),
Container(
width: widthButton,
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(top: 30),
child:
Text('Selamat Datang User, ${SpUtil.getString("name")}'),
),
Container(
width: widthButton,
height: 60,
child: ElevatedButton(
onPressed: () {
//route profil
Get.toNamed(Routes.PROFIL_FORM);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.edit),
SizedBox(
width: 5,
),
Text('Ubah Profil'),
],
),
),
),
Container(
width: widthButton,
height: 60,
margin: EdgeInsets.only(top: 16),
child: ElevatedButton(
onPressed: () {
//route menampilkan list data siswa
Get.toNamed(Routes.SISWA_LIST);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.switch_account),
SizedBox(
width: 5,
),
Text('Data Siswa'),
],
),
),
),
Container(
width: widthButton,
height: 60,
margin: EdgeInsets.only(top: 16),
child: ElevatedButton(
onPressed: () {
SpUtil.clear();
Get.offAllNamed('/login');
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.logout),
SizedBox(
width: 5,
),
Text('Logout'),
],
),
),
),
],
),
),
));
}
}
Pada kode diatas, membuat kode logout, dimana ketika user menekan tombol logout maka kita akan
menghapus semua isi data Sputil dengan perintah clear() lalu kita menghapus semua halaman dan
mengarahkan user ke halaman login.
13. Redirect Auth User
Pada bagian ini kita akan membuat kode dimana jika user telah login, maka setiap aplikasi dijalankan
yang terbuka adalah halaman utama, bukan lagi halaman login, jika user belum login maka halaman
login yang akan ditampilkan.
Jadi kode untuk mengubah data dari class TextEditingController menjadi JSON tidak lagi di controller,
namun di letakkan di class tersendiri.
Membuat class model pada dart dapat dibuat dengan mudah melalui situs
https://javiercbk.github.io/json_to_dart/
Ketik nama class SiswaModel lalu klik tombol Generate dart, klik Copy Dart code to clipboard lalu
pastekan di file siswa_model.dart
SiswaModel(
{this.nisn,
this.nama,
this.kelas,
this.foto,
this.tanggalLahir,
this.updatedAt,
this.createdAt,
this.id,
this.fotoUrl});
Install package intl agar kita bisa mengolah tipe data waktu dengan mudah:
flutter pub add intl
Install image picker untuk menggunakan widget kamera dan image galeri
flutter pub add image_picker
Stop dan Jalankan ulang aplikasi flutter agar semua file package baru dapat terbaca.
Buat tombol untuk berpindah dari siswa_list_view ke siswa_form_view
Buka file siswa_list_view.dart, kita akan membuat tombol tambah menggunakan widget
FloatingActionButton seperti berikut:
Jika kita pelajari kode di file provider yang telah dibuat sebelumnya, semua methodnya membutuhkan
header dan url yang sama, agar kode kita lebih baik, kita bisa membuat satu file misalnya dengan nama
BaseApiProvider lalu provider lain menjadi turunan dari provider ini:
get create provider:BaseApi
if (image != null) {
pathFile.value = image.path;
}
}
void addData() {
String nisn = txtNisn.text;
String nama = txtNama.text;
String kelas = txtKelas.text;
String tanggalLahir = txtTanggalLahir.text;
Pada method addData kita mengubah data dari TextField menjadi objek class SiswaModel lalu mengirim
datanya ke postData yang ada di class SiswaProvider
SiswaModel model = SiswaModel(
nisn: nisn,
nama: nama,
kelas: kelas,
tanggalLahir: tanggalLahir,
foto: pathFile.value,
);
if (pickedDate != null) {
String tanggalSelected =
DateFormat('yyyy-MM-dd').format(pickedDate);
controller.txtTanggalLahir.text = tanggalSelected;
}
},
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () {
controller.addData();
},
child: const Text("Simpan"),
),
],
),
),
),
);
}
}
Pada file siswa_form_view.dart kita membuat textfield dan menampilkan 2 icon button agar user bisa
memilih apakah gambar dipilih dari galeri atau dari camera,
Container(
width: Get.width - 60,
child: controller.pathFile.value == ""
? Icon(
Icons.account_box,
size: 80,
)
: Image.file(
File(controller.pathFile.value),
fit: BoxFit.cover,
),
),
SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () => controller.onTapPicker('galeri'),
icon: Icon(
Icons.image,
size: 40,
),
),
SizedBox(width: 8),
IconButton(
onPressed: () => controller.onTapPicker('camera'),
icon: Icon(
Icons.add_a_photo,
size: 40,
),
),
],
),
Selain itu, kita juga membuat input yang menampilkan date picker seperti berikut:
TextField(
controller: controller.txtTanggalLahir,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Tanggal Lahir",
),
readOnly: true,
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: Get.context!,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2101),
);
if (pickedDate != null) {
controller.txtTanggalLahir.text =
DateFormat('yyyy-MM-dd').format(pickedDate);
}
},
),
void getSiswa() {
EasyLoading.show();
listData.clear();
SiswaProvider().getAll().then((Response response) {
if (response.statusCode == 200) {
var data = response.body['data'];
for (var element in data) {
listData.add(SiswaModel.fromJson(element));
}
} else {
Get.snackbar(
'Ops..Error ${response.statusText}',
'Terjadi kesalahan',
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
EasyLoading.dismiss();
});
}
@override
void onInit() {
getSiswa();
super.onInit();
}
}
Kode Get.snackbar sudah kita buat berulang-ulang, untuk menghemat kode, kita bisa membuat fungsi
untuk snackbar. Buka file main.dart lalu tambahkan kode berikut di bagian paling bawah:
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:sp_util/sp_util.dart';
import 'app/routes/app_pages.dart';