Mobile Programming Prodi SI UBSI
Mobile Programming Prodi SI UBSI
MOBILE Programming
Disusun Oleh:
UNIT PENGEMBANGAN AKADEMIK
Puja dan puji syukur selalu kami panjatkan kehadirat Allah Swt yang telah memberikan semua
nikmatnya sehingga penulis berhasil menyelesaikan modul ajar yang berjudul Mobile Programming ini
tanpa adanya kendala yang berarti. Tujuan dari penyusunan modul ini adalah untuk memudahkan para
mahasiswa Sistem Informasi Fakultas Teknik dan Informatika Universitas Bina Sarana Informatika dalam
mengenl dan memahami mobile programming dan praktik pembuatan API. Modul ini disusun dalam
tahapan agar pemula dapat lebih mudah mempelajarai mobile programming dan mengembangkan
aplikasi mobile yang dikhususkan kepada sistem operasi android.
Keberhasilan penyusunan modul ini tentunya bukan atas usaha penulis saja namun ada banyak
pihak yang turut membantu dan memberikan dukungan untuk suksesnya penulisan modul ini. Untuk
itu, penulis mengucapkan terima kasih yang sebesar-besarnya kepada semua pihak yang telah
memberikan dukungan baik secara moril ataupun material sehingga buku ini berhasil disusun.
Modul yang ada ini tentu tidak luput dari kekurangan. Selalu ada celah untuk perbaikan. Kritik,
saran serta masukkan dari pembaca sangat kami harapkan untuk penyempurnaan kedepannya.
Tim Penulis
2
DAFTAR ISI
3
PERTEMUAN 4 ..................................................................................................................................... 65
1. Membuat Route (Pindah Halaman) ......................................................................................... 65
2. Pemisahan Widget ke dalam Class StatelessWidget ................................................................ 66
3. Menampilkan Detail Produk saat ListView diklik...................................................................... 68
4. Tugas Pertemuan 4 .................................................................................................................. 72
PERTEMUAN 5 ..................................................................................................................................... 73
1. Membuat projek flutter yang terhubung dengan API .............................................................. 73
a. Apa itu API............................................................................................................................ 73
b. Arsitektur API ....................................................................................................................... 73
2. Membuat projek Toko API (Restful API) ................................................................................... 74
a. Installasi Apache, MySql dan PHP (XAMPP) ......................................................................... 74
b. Install Composer .................................................................................................................. 79
c. Install Postman..................................................................................................................... 81
3. API SPEC ................................................................................................................................... 83
a. Registrasi .............................................................................................................................. 83
b. Login..................................................................................................................................... 83
c. Produk .................................................................................................................................. 84
4. Tugas Pertemuan 5 .................................................................................................................. 86
PERTEMUAN 6 ..................................................................................................................................... 87
1. Pembuatan Database ............................................................................................................... 87
a. SQL membuat tabel member ............................................................................................... 87
b. SQL membuat tabel member_token .................................................................................... 87
c. SQL membuat tabel produk ................................................................................................. 87
2. Installasi Lumen sebagai Restful API ........................................................................................ 88
3. Konfigurasi Projek .................................................................................................................... 88
a. Koneksi ke database ............................................................................................................. 88
b. Membuat hasil response ...................................................................................................... 90
4. Registrasi .................................................................................................................................. 91
a. Membuat model Registrasi .................................................................................................. 91
b. Membuat controller Registrasi ............................................................................................ 92
c. Menambah route Registrasi ................................................................................................. 93
PERTEMUAN 7 ..................................................................................................................................... 97
1. Konsep MVC ............................................................................................................................. 97
2. Membuat Login ........................................................................................................................ 97
a. Membuat model Member .................................................................................................... 97
4
b. Membuat model Login ......................................................................................................... 98
c. Membuat controller Login ................................................................................................... 98
d. Menambahkan route Login .................................................................................................. 99
e. Mencoba Rest ...................................................................................................................... 99
3. CRUD Produk .......................................................................................................................... 100
f. Membuat model Produk .................................................................................................... 100
g. Membuat controller produk .............................................................................................. 100
c. Mencoba Rest .................................................................................................................... 104
PERTEMUAN 8 ................................................................................................................................... 107
PERTEMUAN 9 ................................................................................................................................... 108
1. Membangun Projek Dengan Flutter ....................................................................................... 108
2. Pengembangan Projek flutter tokokita .................................................................................. 109
a. Membuat Model ................................................................................................................ 110
b. Membuat Class Login Pada Model ..................................................................................... 110
c. Membuat Class Registrasi Pada Model .............................................................................. 111
d. Membuat Class Produk Pada Model .................................................................................. 111
3. Membuat Halaman ................................................................................................................ 112
a. Membuat Form Registrasi .................................................................................................. 112
b. Membuat Form Login ......................................................................................................... 116
c. Membuat Form Produk ...................................................................................................... 119
d. Membuat Form Detail Produk............................................................................................ 121
e. Membuat Tampilan List Produk ......................................................................................... 122
PERTEMUAN 10 ................................................................................................................................. 128
1. Membuat Helper Modul ........................................................................................................ 128
a. Menambahkan depedencies .............................................................................................. 128
b. Membuat Class Token ........................................................................................................ 128
c. Http request ....................................................................................................................... 130
2. Membuat Bloc ........................................................................................................................ 133
a. Registrasi ............................................................................................................................ 134
b. Login................................................................................................................................... 134
c. Logout ................................................................................................................................ 134
d. Produk ................................................................................................................................ 135
PERTEMUAN 11 ................................................................................................................................. 137
1. Menyatukan Fungsionalitas ................................................................................................... 137
a. Membuat Common Dialog Widget .................................................................................... 137
5
b. Modifikasi main.dart .......................................................................................................... 140
c. Modifikasi registrasi_page.dart .......................................................................................... 141
d. Modifikasi login_page.dart (fungsi login) ........................................................................... 145
PERTEMUAN 12 ................................................................................................................................. 150
1. Modifikasi produk_page.dart ................................................................................................. 150
a. Menambahkan fungsi logout pada drawer ........................................................................ 150
b. Menampilkan Data Produk dari Rest API ........................................................................... 152
2. Memodifikasi Form Produk (produk_form.dart) .................................................................... 155
a. Membuat fungsi simpan .................................................................................................... 155
b. Membuat fungsi ubah ........................................................................................................ 158
PERTEMUAN 13-15 ............................................................................................................................ 165
6
PERTEMUAN I
Saat ini pengembangan aplikasi berbasis mobile lebih terfokus kepada tiga sistem operasi yaitu,
sistem operasi Android, IoS, dan Microsoft. Meskipun diantara ketiganya yang paling terkenal
adalah sistem operasi Android.
Dalam buku ini penekanan pembahasan mobile programming akan difokuskan kepada
penggunaan flutter untuk pengembangan aplikasi mobile dan pengembangan API.
7
b. Perbandingan Flutter dan React Native
Alasan kenapa pada modul ini penekanan pembahasannya pada pengembangan
aplikasi dengan flutter bukan dengan react native disebabkan:
Gambar 1.2 Perbandingan search term dari Flutter vs React Native di Indonesia,
Agustus 2019 – Agustus 2020
Sumber: https://definite.co.id/
Berdasarkan grafik diatas, terlihat bahwa pencarian Flutter (biru) di google angkanya
lebih tinggi dibandingkan dengan React Native (merah) antara tahun 2019 sampai 2020.
Artinya, semakin banyak yang mencari dan mempelajari pembuatan aplikasi mobile
dengan memanfaatkan flutter.
Lebih jelas perbandingan pengembangan aplikasi mobile antara flutter dan react native
ditunjukkan pada gambar 1.3.
9
Kemudian lakukan installasi git dari file yang telah diunduh.
2) Instalasi JDK
JDK (Java Development Kit) adalah sebuah perangkat lunak yang digunakan untuk
melakukan proses kompilasi dari kode java ke bytecode yang dapat dimengerti dan dapat
dijalankan oleh JRE (Java Runtime Envirotment). JDK wajib terinstall pada komputer yang
akan melakukan proses pembuatan aplikasi berbasis java, namun tidak wajib terinstall di
komputer yang akan menjalankan aplikasi yang dibangun dengan java.
JDK dapat diunduh pada laman https://jdk.java.net/
Pilih JDK 15, kemudian download file zip untuk windows, jika menggunakan windows
10
Gambar 1.4 Pilih JDK 15
Sumber : https://jdk.java.net/
11
Kemudian klik tombol “Environtment Variables”
Pilih Path pada bagian System Variables kemudian Klik tombol “Edit”
12
Kemudian klik tombol “New”
13
Kemudian masukkan alamat folder bin pada jdk yang telah kita ekstrak dalam hal ini misalnya
“C:\Program Files\Java\jdk-15.0.1\bin”
14
Biasanya agar JDK dapat berfungsi perlu dilakukan restart laptop/komputer. Untuk
memeriksa apakah installasi berhasil, buka command prompt kemudian ketikkan java -
version atau javac -version
15
Kemudian pilih tipe standar dan klik next
16
Kemudian klik tombol next
Pastikan komputer terhubung dengan internet yang stabil, karena android studio akan
mengunduh komponen-komponen yang diperlukan
17
Setelah selesai klik finish
4) Instalasi Flutter
Flutter adalah sebuah framework open-source yang dikembangkan oleh Google untuk
membangun antarmuka (user interface/UI) aplikasi Android dan iOS.
Apa bedanya membuat aplikasi android menggunakan Java/Kotlin (native) dengan Flutter.
Dari bahasa pemrograman yang digunakan, Flutter menggunakan bahasa pemrograman
Dart, sedangkan Android Native menggunakan bahasa pemrograman Java dan Kotlin.
Aplikasi yang kita buat dengan Flutter dapat di-build ke Android dan iOS. Sedangkan
Android Native hanya bisa di-build ke Android saja.
18
Kemudian pilih flutter_windows_ untuk mengunduh file flutter
19
Kemudian pilih “Advanced System Setting”
20
Kemudian pilih pada “System Variables” pilih “Path” dan klik tombol “Edit”
21
Kemudian klik tombol “New”
22
Kemudian masukkan alamat folder bin pada flutter yang telah kita ekstrak dalam hal ini
misalnya “D:\Android\flutter\bin”
23
5) Konfigurasi Android Studio dengan Flutter
Jalankan Android Studio kemudian pada menu “Configure” pilih “Plugins”
3. Tugas Pertemuan 1
1. Download VSCode pada laman https://code.visualstudio.com/download
2. Lakukan instalasi VSCode dengan mengikuti petunjuk pada Pertemuan 2 part 2 tentang
instalasi VSCode sebagai alternatif editor.
25
PERTEMUAN 2
26
Kemudian tentukan :
Project Name : belajarflutter
Flutter SDK path : D:\Android\flutter (masukkan sesuai alamat folder flutter diletakkan)
Project location : D:\Belajar (bebas memasukkan dimanapun)
Description : Membuat Aplikasi Mobile Flutter (bebas)
Kemudian klik tombol “Next”
Kemudian klik tombol “Finish”. Pastikan perangkat terhubung ke internet, karena diperlukan
untuk mengunduh projek yang dibuat
27
Setelah selesai akan muncul projek yang telah dibuat
Untuk menjalankan projek, kita memerlukan emulator android. Pertama kita akan membuat
emulator android dengan cara klik “AVD Manager” pada pojok kiri atas
28
Kemudian klik tombol “Create Virtual Device”
Pilih salah satu device yang dinginkan, misalnya “Nexus S” kemudian klik tombol “Next”
29
Kemudian kita akan memilih Versi Sistem Operasi Android, dalam hal ini misalnya “Q”, jika
belum ada maka kita akan diminta untuk mengunduh terlebih dahulu.
30
Kemudian akan muncul emulator android seperti berikut:
31
Jika emulator sudah berjalan, kita dapat mengeksekusi projek dengan cara klik tombol play
(berwarna hijau) pada Android Studio
32
2. Membuat dan menjalankan projek dengan VSCode dan Handphone Android
a. Instalasi VSCode sebagai alternatif editor
Unduh VSCode pada laman https://code.visualstudio.com/download kemudian install. Agar flutter
dapat digunakan pada VSCode, perlu diinstall beberapa extension flutter yang dibutuhkan.
33
Kemudian ketikkan flutter dan pilih Flutter: New Application Project
34
Kemudian tentukan nama projek flutter yang ingin dibuat misalnya
aplikasi_flutter_pertamaku
35
c. Menjalankan aplikasi dengan Handphone Android
Untuk menjalankan projek flutter dari VSCode dapat menggunakan Emulator AVD yang telah
dibuat sebelumnya menggunakan Android Studio ataupun menggunakan Device Handphone
Android langsung
Untuk menggunakan android device secara langsung, pertama aktifkan dulu mode developer
dengan cara buka Setting kemudian pilih System kemudian pilih About Phone, untuk masing-
masing device mungkin terdapat perbedaan untuk lokasi About Phone ada pula yang berada
pada Additional Setting
36
Kemudian pilih About Phone
37
Kemudian ketuk Build number beberapa kali, namun ini juga berbeda untuk beberapa versi
misalnya untuk Xiaomi dengan mengetuk MIUI Version beberapa kali
38
Selanjutnya mengaktifkan USB Debugger dengan cara pilih Developer Option pada System,
Developer Option ini akan muncul setelah mode Developer diaktifkan dengan cara diatas
39
Kemudian aktifkan USB Debugging
40
Jika telah selesai, hubungkan Handphone android dengan laptop/komputer dengan kabel
data, untuk memeriksa apakah sudah terhubung dengan Handphone, dapat dilihat pada
VSCode bagian pojok kanan bawah akan tertera nama device yang terhubung
41
Atau jika pada Android Studio terletak pada toolbar bagian atas tengah
Agar laptop bekerja lebih ringan dapat digunakan Text Editor VSCode dan menjalankan projek
langsung menggunakan Handphone Android. Untuk menjalankan projek melalui VSCode
dengan klik logo play pada bagian pojok kanan atas
42
43
3. Struktur Folder Flutter
Adapun struktur folder Projek flutter adalah sebagai berikut:
lib berisi source code Dart, di sini kita akan menulis kode aplikasi;
.metadata merupakan file yang berisi metadata project yang di-generate otomatis;
.packages merupakan file yang berisi alamat path package yang dibuat oleh pub;
pubspec.lock merupakan file yang berisi versi-versi library atau package. File ini dibuat
oleh pub. Fungsinya untuk mengunci versi package.
pubspec.yaml merupakan file yang berisi informasi tentang project dan libraray yang
dibutuhkan;
README.md merupakan file markdown yang berisi penjelasan tentang source code.
44
a. Membuat Hello World
Buka projek aplikasi_flutter_pertamaku menggunakan VSCode agar lebih ringan. Buka file
main.dart yang terletak pada folder lib kemudian ubah menjadi
1. import 'package:flutter/material.dart';
2.
3. void main() {
4. runApp(MyApp());
5. }
6.
7. class MyApp extends StatelessWidget {
8. @override
9. Widget build(BuildContext context) {
10. return MaterialApp(
11. title: 'Aplikasi Flutter Pertama',
12. home: Scaffold(
13. appBar: AppBar(
14. title: Text('Belajar Flutter'),
15. ),
16. ),
17. );
18. }
19. }
45
Kemudian untuk menambahkan tampilan dibagian dalam (body), pada fungsi Scaffold terdapat
parameter body. Silahkan modifikasi main.dart menjadi seperti berikut
1. import 'package:flutter/material.dart';
2.
3. void main() {
4. runApp(MyApp());
5. }
6.
7. class MyApp extends StatelessWidget {
8. @override
9. Widget build(BuildContext context) {
10. return MaterialApp(
11. title: 'Aplikasi Flutter Pertama',
12. home: Scaffold(
46
13. appBar: AppBar(
14. title: Text('Belajar Flutter'),
15. ),
16. body: Center(
17. child: Text('Hello World'),
18. ),
19. ),
20. );
21. }
22. }
Pada aplikasi di atas, kita membuat StatelessWidget yang berisi widget MaterialApp().
Kemudian di dalam MateralApp() berisi widget lagi: Scaffold, AppBar, Center, dan Text.
47
Ini adalah widget dasar.
Penjelasan:
Silahkan buat sebuah file dengan nama hello_world.dart di dalam folder lib
Kemudian bagian Scaffold pada main.dart yang telah dibuat tadi akan kita masukkan ke
dalam hello_world.dart, sehingga pada hello_world.dart akan menjadi
48
1. import 'package:flutter/material.dart';
2.
3. class HelloWorld extends StatelessWidget {
4. @override
5. Widget build(BuildContext context) {
6. return Scaffold(
7. appBar: AppBar(
8. title: Text('Belajar Flutter'),
9. ),
10. body: Center(
11. child: Text('Hello World'),
12. ),
13. );
14. }
15. }
Pada file main.dart kita modifikasi kembali pada bagian home menjadi
1. import 'package:aplikasi_flutter_pertamaku/hello_world.dart';
2. import 'package:flutter/material.dart';
3.
4. void main() {
5. runApp(MyApp());
6. }
7.
8. class MyApp extends StatelessWidget {
9. @override
10. Widget build(BuildContext context) {
11. return MaterialApp(
12. title: 'Aplikasi Flutter Pertama',
13. home: HelloWorld(),
14. );
15. }
16. }
Pada bagian home, kita memanggil class HelloWorld yang telah kita buat sebelumnya
pada file hello_world.dart
Jika kita perhatikan pada bagian body, terdapat Widget Center kemudian didalam Widget
Center tersebut terdapat parameter child untuk meletakkan Widget lain didalam widget
tersebut, dalam hal ini adalah Widget Text
Center(
child: Text('Hello World'),
),
Catatan : dalam Widget selain child, terdapat pula children dengan type data array yang
dimana kita dapat menempatkan beberapa Widget didalamnya contohnya pada Widget
Column dan Row
Untuk mempercepat dalam pembuatan class pada VSCode dapat dilakukan dengan mengetik
st kemudian memilih stateless widget ataupun stateless widget kemudian ketikkan nama
class yang diinginkan
49
b. Membuat Widget Column
Buat sebuah file dengan nama column_widget.dart didalam folder lib, kemudian ketikkan
kode berikut
1. import 'package:flutter/material.dart';
2.
3. class ColumnWidget extends StatelessWidget {
4. @override
5. Widget build(BuildContext context) {
6. return Scaffold(
7. appBar: AppBar(
8. title: Text('Widget Column'),
9. ),
10. body: Column(
11. children: [
12. Text('Kolom 1'),
13. Text('Kolom 2'),
14. Text('Kolom 3'),
15. Text('Kolom 4'),
16. ],
17. ),
18. );
19. }
20. }
50
Column biasanya digunakan untuk membuat Form
c. Membuat Widget Row
Untuk menampilkan Widget dalam posisi horizontal dapat menggunakan Widget Row. Buat
sebuah file didalam folder lib dengan nama row_widget.dart, kemudian ketikkan kode berikut
1. import 'package:flutter/material.dart';
2.
3. class RowWidget extends StatelessWidget {
4. @override
5. Widget build(BuildContext context) {
6. return Scaffold(
7. appBar: AppBar(
8. title: Text('Widget Row'),
51
9. ),
10. body: Row(
11. children: [
12. Text('Row 1'),
13. Text('Row 2'),
14. Text('Row 3'),
15. Text('Row 4'),
16. ],
17. ),
18. );
19. }
20. }
Kemudian seperti sebelumnya masukkan class RowWidget tersebut kedalam home pada
main.dart, dan hasilnya akan menjadi
52
d. Mengenal StatelessWidget dan StatefullWidget
StatelessWidget adalah class widget yang propertinya immutable, artinya nilainya tidak bisa
diubah, sedangkan StatefullWidget nilainya dapat berubah-ubah.
Contoh StatelessWidget :
Contoh StatefullWidget
53
4. Tugas Pertemuan 2
1. Membuat Form dengan flutter dengan mengikuti Langkah-langkah seperti berikut ini:
a. Untuk membuat form dengan flutter, agar lebih rapi untuk tampilan halaman akan kita
kelompokkan dalam sebuah folder tersendiri, dalam hal ini kita membuat folder dengan
nama ui didalam folder lib.
Kemudian didalam folder ui tersebut kita buat sebuah file dengan nama produk_form.dart
54
Kemudian Ketikkan kode berikut
55
1. import 'package:flutter/material.dart';
2.
3. class ProdukForm extends StatefulWidget {
4. @override
5. _ProdukFormState createState() => _ProdukFormState();
6. }
7.
8. class _ProdukFormState extends State<ProdukForm> {
9. @override
10. Widget build(BuildContext context) {
11. return Scaffold(
12. appBar: AppBar(
13. title: Text('Form Produk'),
14. ),
15. body: SingleChildScrollView(
16. child: Column(
17. children: [
18. TextField(
19. decoration: InputDecoration(labelText: "Kode Produk"),
20. ),
21. TextField(
22. decoration: InputDecoration(labelText: "Nama Produk"),
23. ),
24. TextField(
25. decoration: InputDecoration(labelText: "Harga"),
26. ),
27. RaisedButton(
28. child: Text('Simpan'),
29. onPressed: () {},
30. )
31. ],
32. ),
33. ),
34. );
35. }
36. }
b. Ubah pada main.dart dengan memanggil class ProdukForm, sehingga hasilnya akan
menjadi
56
57
PERTEMUAN 3
1. import 'package:flutter/material.dart';
2.
3. class ProdukForm extends StatefulWidget {
4. @override
5. _ProdukFormState createState() => _ProdukFormState();
6. }
7.
8. class _ProdukFormState extends State<ProdukForm> {
9. @override
10. Widget build(BuildContext context) {
11. return Scaffold(
12. appBar: AppBar(
13. title: Text('Form Produk'),
14. ),
15. body: SingleChildScrollView(
16. child: Column(
17. children: [
18. _textboxKodeProduk(),
19. _textboxNamaProduk(),
20. _textboxHargaProduk(),
21. _tombolSimpan()
22. ],
23. ),
24. ),
25. );
26. }
27.
28. _textboxKodeProduk() {
29. return TextField(
30. decoration: InputDecoration(labelText: "Kode Produk"),
31. );
32. }
33.
34. _textboxNamaProduk() {
35. return TextField(
36. decoration: InputDecoration(labelText: "Nama Produk"),
37. );
38. }
39.
40. _textboxHargaProduk() {
41. return TextField(
42. decoration: InputDecoration(labelText: "Harga"),
43. );
44. }
45.
46. _tombolSimpan() {
47. return RaisedButton(
48. child: Text('Simpan'),
49. onPressed: () {},
50. );
58
51. }
52. }
1. import 'package:flutter/material.dart';
2.
3. class ProdukDetail extends StatefulWidget {
4. final String kodeProduk;
5. final String namaProduk;
6. final int harga;
7.
8. ProdukDetail({this.kodeProduk, this.namaProduk, this.harga});
9.
10. @override
11. _ProdukDetailState createState() => _ProdukDetailState();
12. }
13.
14. class _ProdukDetailState extends State<ProdukDetail> {
15. @override
16. Widget build(BuildContext context) {
17. return Scaffold(
18. appBar: AppBar(
19. title: Text("Detail Produk"),
20. ),
21. body: Column(
22. children: [
23. Text("Kode Produk : " + widget.kodeProduk),
24. Text("Nama Produk : ${widget.namaProduk}"), // jika didalam String
25. Text("Harga : ${widget.harga.toString()}"), // jika didalam String
26. ],
27. ),
28. );
29. }
30. }
4. Membuat fungsi tombol simpan dan menampilkan data pada Detail Produk
Buka kembali file produk_form.dart tambahkan attribute
final _kodeProdukTextboxController = TextEditingController();
final _namaProdukTextboxController = TextEditingController();
final _hargaProdukTextboxController = TextEditingController();
1. import 'package:flutter/material.dart';
2.
3. class ProdukForm extends StatefulWidget {
4. @override
5. _ProdukFormState createState() => _ProdukFormState();
6. }
7.
8. class _ProdukFormState extends State<ProdukForm> {
9.
10. final _kodeProdukTextboxController = TextEditingController();
11. final _namaProdukTextboxController = TextEditingController();
12. final _hargaProdukTextboxController = TextEditingController();
13.
14. @override
59
15. Widget build(BuildContext context) {
16. return Scaffold(
17. appBar: AppBar(
18. title: Text('Form Produk'),
19. ),
20. body: SingleChildScrollView(
21. child: Column(
22. children: [
23. _textboxKodeProduk(),
24. _textboxNamaProduk(),
25. _textboxHargaProduk(),
26. _tombolSimpan()
27. ],
28. ),
29. ),
30. );
31. }
32.
33. _textboxKodeProduk() {
34. return TextField(
35. decoration: InputDecoration(labelText: "Kode Produk"),
36. );
37. }
38.
39. _textboxNamaProduk() {
40. return TextField(
41. decoration: InputDecoration(labelText: "Nama Produk"),
42. );
43. }
44.
45. _textboxHargaProduk() {
46. return TextField(
47. decoration: InputDecoration(labelText: "Harga"),
48. );
49. }
50.
51. _tombolSimpan() {
52. return RaisedButton(
53. child: Text('Simpan'),
54. onPressed: () {},
55. );
56. }
57. }
Pada setiap masing-masing TextField yang telah dibuat data yang diinput dikirim ke attribute
TextEditingController() yang telah kita buat sebelumnya
Pada fungsi _textboxKodeProduk() menjadi
_textboxKodeProduk() {
return TextField(
decoration: InputDecoration(labelText: "Kode Produk"),
controller: _kodeProdukTextboxController,
);
}
Kemudian pada fungsi _tombolSimpan() pada saat diklik akan mengirim data inputan dan
menampilkan data tersebut pada ProdukDetail yang telah kita buat sebelumnya
_tombolSimpan() {
return RaisedButton(
child: Text('Simpan'),
onPressed: () {
String kode_produk = _kodeProdukTextboxController.text;
String nama_produk = _namaProdukTextboxController.text;
int harga = int.parse(_hargaProdukTextboxController.text); //parsing dari String ke
int
// pindah ke halaman Produk Detail dan mengirim data
Navigator.of(context).push(new MaterialPageRoute(builder: (context)=>ProdukDetail(k
odeProduk: kode_produk, namaProduk: nama_produk, harga: harga,)));
},
);
}
1. import 'package:aplikasi_flutter_pertamaku/ui/produk_detail.dart';
2. import 'package:flutter/material.dart';
3.
4. class ProdukForm extends StatefulWidget {
5. @override
6. _ProdukFormState createState() => _ProdukFormState();
7. }
8.
9. class _ProdukFormState extends State<ProdukForm> {
10. final _kodeProdukTextboxController = TextEditingController();
11. final _namaProdukTextboxController = TextEditingController();
12. final _hargaProdukTextboxController = TextEditingController();
13.
14. @override
15. Widget build(BuildContext context) {
16. return Scaffold(
17. appBar: AppBar(
18. title: Text('Form Produk'),
19. ),
20. body: SingleChildScrollView(
21. child: Column(
22. children: [
23. _textboxKodeProduk(),
24. _textboxNamaProduk(),
25. _textboxHargaProduk(),
26. _tombolSimpan()
61
27. ],
28. ),
29. ),
30. );
31. }
32.
33. _textboxKodeProduk() {
34. return TextField(
35. decoration: InputDecoration(labelText: "Kode Produk"),
36. controller: _kodeProdukTextboxController,
37. );
38. }
39.
40. _textboxNamaProduk() {
41. return TextField(
42. decoration: InputDecoration(labelText: "Nama Produk"),
43. controller: _namaProdukTextboxController,
44. );
45. }
46.
47. _textboxHargaProduk() {
48. return TextField(
49. decoration: InputDecoration(labelText: "Harga"),
50. controller: _hargaProdukTextboxController,
51. );
52. }
53.
54. _tombolSimpan() {
55. return RaisedButton(
56. child: Text('Simpan'),
57. onPressed: () {
58. String kode_produk = _kodeProdukTextboxController.text;
59. String nama_produk = _namaProdukTextboxController.text;
60. int harga = int.parse(_hargaProdukTextboxController.text); //parsing dari St
ring ke int
61. // pindah ke halaman Produk Detail dan mengirim data
62. Navigator.of(context).push(new MaterialPageRoute(builder: (context)=>ProdukD
etail(kodeProduk: kode_produk, namaProduk: nama_produk, harga: harga,)));
63. },
64. );
65. }
66. }
62
5. Membuat ListView Produk
Buat sebuah file dengan nama produk_page.dart di dalam folder ui, kemudian ketikkan kode
berikut
1. import 'package:flutter/material.dart';
2.
3. class ProdukPage extends StatefulWidget {
4. @override
5. _ProdukPageState createState() => _ProdukPageState();
6. }
7.
8. class _ProdukPageState extends State<ProdukPage> {
9. @override
10. Widget build(BuildContext context) {
11. return Scaffold(
12. appBar: AppBar(
13. title: Text("Data Produk"),
14. ),
15. body: ListView(
16. children: [
17. //list 1
18. Card(
19. child: ListTile(
20. title: Text("Kulkas"),
21. subtitle: Text("2500000"),
22. ),
23. ),
24. //list 2
63
25. Card(
26. child: ListTile(
27. title: Text("TV"),
28. subtitle: Text("5000000"),
29. ),
30. ),
31. //list 3
32. Card(
33. child: ListTile(
34. title: Text("Mesin Cuci"),
35. subtitle: Text("1500000"),
36. ),
37. ),
38. ],
39. ),
40. );
41. }
42. }
Kemudian daftarkan ProdukPage pada main.dart, dan hasilnya akan menjadi seperti berikut
6. Tugas Pertemuan 3
64
PERTEMUAN 4
1. import 'package:aplikasi_flutter_pertamaku/ui/produk_form.dart';
2. import 'package:flutter/material.dart';
3.
4. class ProdukPage extends StatefulWidget {
5. @override
6. _ProdukPageState createState() => _ProdukPageState();
7. }
8.
9. class _ProdukPageState extends State<ProdukPage> {
10. @override
11. Widget build(BuildContext context) {
12. return Scaffold(
13. appBar: AppBar(
14. title: Text("Data Produk"),
15. actions: [
16. GestureDetector(
17. // menampilkan icon +
18. child: Icon(Icons.add),
19. //pada saat icon + di tap
20. onTap: () async {
21. //berpindah ke halaman ProdukForm
22. Navigator.push(context,
23. new MaterialPageRoute(builder: (context) => ProdukForm()));
24. },
25. )
26. ],
27. ),
28. body: ListView(
29. children: [
30. //list 1
31. Card(
32. child: ListTile(
33. title: Text("Kulkas"),
34. subtitle: Text("2500000"),
35. ),
65
36. ),
37. //list 2
38. Card(
39. child: ListTile(
40. title: Text("TV"),
41. subtitle: Text("5000000"),
42. ),
43. ),
44. //list 3
45. Card(
46. child: ListTile(
47. title: Text("Mesin Cuci"),
48. subtitle: Text("500000"),
49. ),
50. ),
51. ],
52. ),
53. );
54. }
55. }
Hasilnya akan muncul icon + pada bagian kanan AppBar, jika diklik akan membuka
ProdukForm
1. import 'package:aplikasi_flutter_pertamaku/ui/produk_form.dart';
2. import 'package:flutter/material.dart';
3.
4. class ProdukPage extends StatefulWidget {
5. @override
6. _ProdukPageState createState() => _ProdukPageState();
7. }
8.
9. class _ProdukPageState extends State<ProdukPage> {
10. @override
11. Widget build(BuildContext context) {
12. return Scaffold(
13. appBar: AppBar(
14. title: Text("Data Produk"),
15. actions: [
16. GestureDetector(
17. // menampilkan icon +
18. child: Icon(Icons.add),
19. //pada saat icon + di tap
20. onTap: () async {
21. //berpindah ke halaman ProdukForm
22. Navigator.push(context,
23. new MaterialPageRoute(builder: (context) => ProdukForm()));
24. },
25. )
26. ],
27. ),
28. body: ListView(
29. children: [
30. //list 1
31. ItemProduk(
32. kodeProduk: "A001",
33. namaProduk: "Kulkas",
34. harga: 2500000,
35. ),
36. //list 2
37. ItemProduk(
38. kodeProduk: "A002",
39. namaProduk: "TV",
40. harga: 5000000,
67
41. ),
42. //list 3
43. ItemProduk(
44. kodeProduk: "A003",
45. namaProduk: "Mesin Cuci",
46. harga: 1500000,
47. ),
48. ],
49. ),
50. );
51. }
52. }
53.
54. class ItemProduk extends StatelessWidget {
55. final String kodeProduk;
56. final String namaProduk;
57. final int harga;
58.
59. //membuat constructor
60. ItemProduk({this.kodeProduk, this.namaProduk, this.harga});
61.
62. @override
63. Widget build(BuildContext context) {
64. return Card(
65. child: ListTile(
66. title: Text(namaProduk),
67. subtitle: Text(harga.toString()), //parsing dari int ke string
68. ),
69. );
70. }
71. }
68
Pada bagian kiri akan muncul logo lampu, kemudian klik lampu tersebut dan pilih widget yang
ingin ditambahkan atau dalam hal ini kita akan memilih Warp with widget..
Setelah itu ubah widget menjadi GestureDetector dan kita juga menambahkan onTap yang
kemudian akan membuka halaman Detail Produk, sehingga kode untuk Class ItemProduk
menjadi
class ItemProduk extends StatelessWidget {
final String kodeProduk;
final String namaProduk;
final int harga;
69
//membuat constructor
ItemProduk({this.kodeProduk, this.namaProduk, this.harga});
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Card(
child: ListTile(
title: Text(namaProduk),
subtitle: Text(harga.toString()), //parsing dari int ke string
),
),
onTap: () {
// pindah ke halaman Produk Detail dan mengirim data
Navigator.of(context).push(new MaterialPageRoute(
builder: (context) => ProdukDetail(
kodeProduk: kodeProduk,
namaProduk: namaProduk,
harga: harga,
)));
},
);
}
}
1. import 'package:aplikasi_flutter_pertamaku/ui/produk_detail.dart';
2. import 'package:aplikasi_flutter_pertamaku/ui/produk_form.dart';
3. import 'package:flutter/material.dart';
4.
5. class ProdukPage extends StatefulWidget {
6. @override
7. _ProdukPageState createState() => _ProdukPageState();
8. }
9.
10. class _ProdukPageState extends State<ProdukPage> {
11. @override
12. Widget build(BuildContext context) {
13. return Scaffold(
14. appBar: AppBar(
15. title: Text("Data Produk"),
16. actions: [
17. GestureDetector(
18. // menampilkan icon +
19. child: Icon(Icons.add),
20. //pada saat icon + di tap
21. onTap: () async {
22. //berpindah ke halaman ProdukForm
23. Navigator.push(context,
24. new MaterialPageRoute(builder: (context) => ProdukForm()));
25. },
26. )
27. ],
28. ),
29. body: ListView(
30. children: [
31. //list 1
32. ItemProduk(
33. kodeProduk: "A001",
34. namaProduk: "Kulkas",
70
35. harga: 2500000,
36. ),
37. //list 2
38. ItemProduk(
39. kodeProduk: "A002",
40. namaProduk: "TV",
41. harga: 5000000,
42. ),
43. //list 3
44. ItemProduk(
45. kodeProduk: "A003",
46. namaProduk: "Mesin Cuci",
47. harga: 1500000,
48. ),
49. ],
50. ),
51. );
52. }
53. }
54.
55. class ItemProduk extends StatelessWidget {
56. final String kodeProduk;
57. final String namaProduk;
58. final int harga;
59.
60. //membuat constructor
61. ItemProduk({this.kodeProduk, this.namaProduk, this.harga});
62.
63. @override
64. Widget build(BuildContext context) {
65. return GestureDetector(
66. child: Card(
67. child: ListTile(
68. title: Text(namaProduk),
69. subtitle: Text(harga.toString()), //parsing dari int ke string
70. ),
71. ),
72. onTap: () {
73. // pindah ke halaman Produk Detail dan mengirim data
74. Navigator.of(context).push(new MaterialPageRoute(
75. builder: (context) => ProdukDetail(
76. kodeProduk: kodeProduk,
77. namaProduk: namaProduk,
78. harga: harga,
79. )));
80. },
81. );
82. }
83. }
71
4. Tugas Pertemuan 4
a. Mendownload XAMPP, Composer dan Postman untuk kebutuhan pertemuan 5! (Link
download bisa diakses pada modul pertemuan 5)
b. Melakukan instalasi XAMPP, Composer dan Postman sesuai dengan Langkah-langkah
yang ada pada pertemuan 5!
c. Memastikan keberhasilan tahapan poin a dan b sebelum memasuki pertemuan 5!
72
PERTEMUAN 5
Sumber : codepolitan.com
b. Arsitektur API
Ada tiga arsitektur API yang sering digunakan oleh developer dalam pembangunan aplikasi. Arsitektur
ini berkaitan pada bentuk data yang dikirim. Adapun Arsitektur API yang sering digunakan adalah
1. RPC
RPC merupakan teknologi untuk membuat komunikasi antara client side dan server side bisa dilakukan
dengan konsep sederhana.
RPC memiliki dua jenis, yaitu XML-RPC dan JSON-RPC. Sesuai namanya, XML-RPC menggunakan format
XML sebagai media perpindahan data, sedangkan JSON-RPC menggunakan JSON untuk perpindahan
data.
2. SOAP
Arsitektur API lainnya adalah SOAP (Simple Object Access Protocol). Arsitektur ini menggunakan XML
(Extensible Markup Language) yang memungkinkan semua data disimpan dalam dokumen.
3. REST
REST atau Representational State Transfer adalah arsitektur API yang cukup populer karena
kemudahan penggunaannya. Tak perlu coding yang panjang untuk menggunakannya.
73
REST menggunakan JSON sebagai bentuk datanya sehingga lebih ringan. Performa aplikasi pun
menjadi lebih baik.
2. Membuat projek Toko API (Restful API)
a. Installasi Apache, MySql dan PHP (XAMPP)
XAMPP adalah perangkat lunak untuk membuat komputer menjadi web server. XAMPP dapat
di download melalui link url:
https://www.apachefriends.org/download.html.
Setelah itu, double klik file xampp yang baru di download. Jika muncul pesan error seperti
gambar dibawah, abaikan saja dan lanjutkan klik tombol OK.
Berikutnya akan muncul jendela Setup-XAMPP. Klik tombol Next untuk melanjutkan proses
berikutnya.
Selanjutnya akan muncul jendela Select Components, yang meminta untuk memilih aplikasi
yang akan diinstall. Centang saja semua kemudian klik tombol Next.
74
Kemudian akan muncul jendela Installation Folder, dimana anda diminta untuk menentukan
lokasi penyimpanan folder xampp, secara bawaan akan diarahkan ke lokasi c:\xampp. Jika anda
ingin menyimpannya di folder lain, anda dapat menekan tombol bergambar folder (Browse),
kemudian klik tombol Next.
Kita akan menjumpai jendela tawaran untuk mempelajari lebih lanjut tentang Bitnami. Silahkan
checklist jika ingin mempelajari lebih lanjut. Bitnami adalah pustaka dari aplikasi client server
75
yang populer seperti misalnya CMS WordPress atau Drupal, dengan penawaran kemudahan
dalam installasi hanya dengan satu klik. Kemudian klik tombol Next.
Kemudian muncul jendela Ready To Install yang menunjukkan xampp sudah siap di install.
Kemudian klik tombol Next.
76
Tunggu hingga proses install selesai dan muncul jendela sebagai berikut.
Klik tombol Finish setelah itu akan muncul jendela Xampp Control Panel yang berguna untuk
menjalankan server.
77
Klik tombol Start pada kolom Actions untuk module Apache dan MySQL.
Untuk mengetahui apakah installasi telah berhasil atau tidak, ketikkan ‘localhost/’ pada
browser, jika berhasil akan muncul halaman seperti gambar dibawah.
78
b. Install Composer
Composer adalah Dependency Management Tools untuk PHP. Sederhananya Composer akan
membantu kita mencari dan mendownload file-file yang diperlukan oleh sebuah aplikasi yang
akan install yang akan tersimpan pada folder vendor. Composer untuk windows dapat
didownload di https://getcomposer.org/Composer-Setup.exe. Install composer sangat mudah,
cukup double klik file composer yang telah di download.
Pada jendela Selects Components kita dapat lanjutkan dengan menekan tombol Next.
79
Pada umumnya secara otomatis composer akan mendapatkan file php.exe yang telah kita
install sebelumnya (Installasi XAMPP). Lanjutkan dengan menekan tombol Next dan Install.
80
c. Install Postman
Postman adalah sebuah aplikasi fungsinya adalah sebagai REST Client atau istilahnya
adalah aplikasi yang digunakan untuk melakukan uji coba REST API yang telah kita buat.
Postman ini merupakan tools wajib bagi para developer yang bergerak pada pembuatan API,
fungsi utama postman ini adalah sebagai GUI API Caller Pemanggil. namun sekarang postman
juga menyediakan fitur lain yaitu Sharing Collection API for Documentation (free), Testing API
(free), Realtime Collaboration Team (paid), Monitoring API (paid), Integration (paid).
Postman tersedia sebagai aplikasi asli untuk sistem operasi macOS, Windows (32-bit dan
64-bit), dan Linux (32-bit dan 64-bit). Untuk mendapatkan aplikasi Postman, dapat diunduh
pada website resminya yanitu getpostman.com atau dapat diunduk pada halaman
https://www.postman.com/downloads/
Setelah berhasil mengunduh paket instalasi postman, kemudian jalankan dengan cara klik dua
kali. Pilih run jika muncul pop up seperti berikut :
81
Kemudian tunggu hingga proses instalasi selesai dan muncul seperti gambar berikut
82
3. API SPEC
API SPEC ini bermaksud untuk membuat standar API sebagai dokumentasi kepada
pengembang baik itu frontend maupun backend
a. Registrasi
EndPoint /registrasi
Method POST
Header • Content-Type: application/json
Body {
"nama" : "string",
"email" : "string, unique",
"password" : "string"
}
Response {
"code" : "integer",
"status" : "boolean",
"data" : "string"
}
b. Login
EndPoint /login
Method POST
Header • Content-Type: application/json
Body {
"email" : "string"
"password" : "string"
}
Response {
"code" : "integer",
"status" : "boolean",
"data" : {
"token" : "string",
"user" : {
"id" : "integer",
"email" : "string",
}
}
}
83
c. Produk
1) List Produk
EndPoint /produk
Method GET
Header • Content-Type: application/json
Response {
"code" : "integer",
"status" : "boolean",
"data" : [
{
"id" : "integer",
"kode_produk" : "string",
"nama_produk" : "string",
"harga" : "integer",
},
{
"id" : "integer",
"kode_produk" : "string",
"nama_produk" : "string",
"harga" : "integer",
}
]
}
2) Create Produk
EndPoint /produk
Method POST
Header • Content-Type: application/json
Body {
"kode_produk" : "string",
"nama_produk" : "string",
"harga" : "integer"
}
Response {
"code" : "integer",
"status" : "boolean",
"data" : {
"id" : "integer",
"kode_produk" : "string",
"nama_produk" : "string",
"harga" : "integer",
}
}
84
3) Update Produk
EndPoint /produk/{id}/update
Method POST
Header • Content-Type: application/json
Body {
"kode_produk" : "string",
"nama_produk" : "string",
"harga" : "integer"
}
Response {
"code" : "integer",
"status" : "boolean",
"data" : "boolean"
}
4) Show Produk
EndPoint /produk/{id}
Method GET
Header • Content-Type: application/json
Response {
"code" : "integer",
"status" : "boolean",
"data" : {
"id" : "integer",
"kode_produk" : "string",
"nama_produk" : "string",
"harga" : "integer",
}
}
5) Delete Produk
EndPoint /produk/{id}
Method DELETE
Header • Content-Type: application/json
Response {
"code" : "integer",
"status" : "boolean",
"data" : "boolean"
}
85
4. Tugas Pertemuan 5
d. Download Lumen untuk persiapan pertemuan 6 dan lakukan instalasi Lumen sesuai
petunjuk yang ada pada pertemuan 6
e. Memastikan Lumen sudah terinstalasi sebelum pertemuan 6 dimulai.
86
PERTEMUAN 6
1. Pembuatan Database
Buat database dengan nama : toko_api
87
id INT NOT NULL AUTO_INCREMENT,
kode_produk VARCHAR(255) NOT NULL,
nama_produk VARCHAR(255) NOT NULL,
harga INT NOT NULL,
PRIMARY KEY(id)
);
Untuk membuat projek lumen dapat menggunakan composer pada command prompt dengan
menjalankan perintah
Sekarang kita akan membuat projek Restful API dengan nama toko-api. Silahkan buka
Command Prompt kemudian ketikkan perintah
C:\Users\BSI\> cd c:\xampp\htdocs
3. Konfigurasi Projek
a. Koneksi ke database
Buka file .env kemudian ubah kode berikut
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
Menjadi sebagai berikut
88
DB_DATABASE=toko_api
DB_USERNAME=root
DB_PASSWORD=
Kemudian hilangkan komentar pada kode berikut (pada baris 26 dan 28)
// $app->withFacades();
89
// $app->withEloquent();
Menjadi
$app->withFacades();
$app->withEloquent();
90
<?php
namespace App\Http\Controllers;
4. Registrasi
a. Membuat model Registrasi
Buat sebuah file dengan nama Registrasi.php pada folder “app/Models”
<?php
namespace App\Models;
91
use Illuminate\Database\Eloquent\Model;
92
<?php
namespace App\Http\Controllers;
use App\Models\Registrasi;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
Registrasi::create([
'nama' => $nama,
'email' => $email,
'password' => $password,
]);
return $this->responseHasil(200, true, "Registrasi Berhasil");
}
}
93
Kemudian tambahkan kode berikut:
94
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/
Pada baris terakhir kita menambahkan routing registrasi agar dapat diakses. Untuk mengakses
registrasi, kita gunakan Postman dengan alamat url localhost/toko-api/public/registrasi dengan
method POST
Adapun langkah menggunakan postman untuk menguji Rest API yang telah dibuat adalah
sebagai berikut:
$nama = $request->input('nama');
$email = $request->input('email');
$password = Hash::make($request->input('password'));
95
96
PERTEMUAN 7
1. Konsep MVC
Sama seperti Framework Php pada umumnya, Lumen juga mengusung konsep MVC dalam
Design Pattern.
MVC adalah konsep arsitektur dalam pembangunan aplikasi yang membagi aplikasi menjadi 3
bagian besar. Yang mana setiap bagian memiliki tugas-tugas serta tanggung jawab masing-
masing. Tiga bagian tersebut adalah: model, view dan controller.
• Model: Bertugas untuk mengatur, menyiapkan, memanipulasi dan mengorganisasikan
data (dari database) sesuai dengan instruksi dari controller.
• View: Bertugas untuk menyajikan informasi (yang mudah dimengerti) kepada user
sesuai dengan instruksi dari controller.
• Controller: Bertugas untuk mengatur apa yang harus dilakukan model, dan view mana
yang harus ditampilkan berdasarkan permintaan dari user
2. Membuat Login
a. Membuat model Member
Buat sebuah file dengan nama Member.php pada folder Models dan ketikkan kode berikut
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
97
b. Membuat model Login
Buat sebuah file dengan nama Login.php pada folder “app/Models” dan ketikkan kode
berikut
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
<?php
namespace App\Http\Controllers;
use App\Models\Login;
use App\Models\Member;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
98
$login = Login::create([
'member_id' => $member->id,
'auth_key' => $this->RandomString(),
]);
if (!$login) {
return $this->responseHasil(401, false, 'Unauthorized');
}
$data = [
'token' => $login->auth_key,
'user' => [
'id' => $member->id,
'email' => $member->email,
]
];
return $this->responseHasil(200, true, $data);
}
e. Mencoba Rest
Silahkan coba Rest API dengan memasukkan url http://localhost/toko-api/public/login dengan
method POST
99
3. CRUD Produk
f. Membuat model Produk
Buat sebuah file dengan nama Produk.php pada folder “app/Models” dan ketikkan kode
berikut
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
<?php
namespace App\Http\Controllers;
use App\Models\Produk;
use Illuminate\Http\Request;
Selanjutnya pada class ProdukController kita akan menambahkan fungsi (function) CRUD
produk, yaitu:
$produk = Produk::create([
'kode_produk' => $kodeProduk,
'nama_produk' => $namaProduk,
'harga' => $harga,
]);
return $this->responseHasil(200, true, $produk);
}
$produk = Produk::findOrFail($id);
$result = $produk->update([
'kode_produk' => $kodeProduk,
101
'nama_produk' => $namaProduk,
'harga' => $harga,
]);
return $this->responseHasil(200, true, $result);
}
<?php
namespace App\Http\Controllers;
use App\Models\Produk;
use Illuminate\Http\Request;
$produk = Produk::create([
'kode_produk' => $kodeProduk,
'nama_produk' => $namaProduk,
'harga' => $harga,
]);
return $this->responseHasil(200, true, $produk);
}
$produk = Produk::findOrFail($id);
$result = $produk->update([
'kode_produk' => $kodeProduk,
'nama_produk' => $namaProduk,
'harga' => $harga,
]);
return $this->responseHasil(200, true, $result);
}
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
103
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/
c. Mencoba Rest
Create Produk (localhost/toko-api/public/produk) dengan method POST
104
List Produk (localhost/toko-api/public/produk) dengan method GET
105
Update Produk (localhost/toko-api/public/produk/{id}/update) dengan method POST
106
PERTEMUAN 8
107
PERTEMUAN 9
108
Untuk proses mengambil data dapat digambarkan sebagai berikut
Bloc akan mengambil data dari API kemudian menterjemahkan kedalam Objek Model yang
kemudian ditampilkan ke UI
109
a. Membuat Model
Buat folder dengan nama model pada folder lib
1. class Login{
110
2. int code;
3. bool status;
4. String token;
5. int userID;
6. String userEmail;
7.
8. Login({this.code, this.status,this.token, this.userID, this.userEmail});
9.
10. factory Login.fromJson(Map<String, dynamic> obj) {
11. return Login(
12. code: obj['code'],
13. status: obj['status'],
14. token: obj['data']['token'],
15. userID: obj['data']['user']['id'],
16. userEmail: obj['data']['user']['email']
17. );
18. }
19. }
1. class Registrasi {
2. int code;
3. bool status;
4. String data;
5.
6. Registrasi({this.code, this.status, this.data});
7.
8. factory Registrasi.fromJson(Map<String, dynamic> obj) {
9. return Registrasi(
10. code: obj['code'],
11. status: obj['status'],
12. data: obj['data']
13. );
14. }
15. }
1. class Produk{
2. int id;
3. String kodeProduk;
4. String namaProduk;
5. int hargaProduk;
6.
7. Produk({this.id, this.kodeProduk, this.namaProduk, this.hargaProduk});
8.
9. factory Produk.fromJson(Map<String, dynamic> obj) {
10. return Produk(
11. id: obj['id'],
12. kodeProduk: obj['kode_produk'],
13. namaProduk: obj['nama_produk'],
14. hargaProduk: obj['harga']
15. );
111
16. }
17. }
3. Membuat Halaman
Pertama kita akan memecah bagian-bagian kode menjadi beberapa bagian, adapun untuk
tampilan, dikelompokkan kedalam folder ui.
112
Pada file registrasi_page.dart ketikkan kode berikut
1. import 'package:flutter/material.dart';
2.
3. class RegistrasiPage extends StatefulWidget {
4. @override
5. _RegistrasiPageState createState() => _RegistrasiPageState();
6. }
7.
8. class _RegistrasiPageState extends State<RegistrasiPage> {
9. final _formKey = GlobalKey<FormState>();
10. bool _isLoading = false;
11.
12. final _namaTextboxController = TextEditingController();
13. final _emailTextboxController = TextEditingController();
14. final _passwordTextboxController = TextEditingController();
15.
16. @override
17. Widget build(BuildContext context) {
18. return Scaffold(
19. appBar: AppBar(title: Text("Registrasi"),),
20. body: SingleChildScrollView(
21. child: Container(
22. child: Padding(
23. padding: const EdgeInsets.all(8.0),
24. child: Form(
25. key: _formKey,
26. child: Column(
27. mainAxisAlignment: MainAxisAlignment.center,
28. children: [
29. _namaTextField(),
113
30. _emailTextField(),
31. _passwordTextField(),
32. _passwordKonfirmasiTextField(),
33. _buttonRegistrasi()
34. ],
35. ),
36. ),
37. ),
38. ),
39. ),
40. );
41. }
42.
43. //Membuat Textbox Nama
44. Widget _namaTextField() {
45. return TextFormField(
46. decoration: InputDecoration(labelText: "Nama"),
47. keyboardType: TextInputType.text,
48. controller: _namaTextboxController,
49. validator: (value){
50. if(value.length < 3){
51. return "Nama harus diisi minimal 3 karakter";
52. }
53. return null;
54. },
55. );
56. }
57.
58. //Membuat Textbox email
59. Widget _emailTextField() {
60. return TextFormField(
61. decoration: InputDecoration(labelText: "Email"),
62. keyboardType: TextInputType.emailAddress,
63. controller: _emailTextboxController,
64. validator: (value){
65. //validasi harus diisi
66. if(value.isEmpty){
67. return 'Email harus diisi';
68. }
69. //validasi email
70. Pattern pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\
".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-
9]+\.)+[a-zA-Z]{2,}))$';
71. RegExp regex = new RegExp(pattern);
72. if (!regex.hasMatch(value)) {
73. return "Email tidak valid";
74. }
75. return null;
76. },
77. );
78. }
79.
80. //Membuat Textbox password
81. Widget _passwordTextField() {
82. return TextFormField(
83. decoration: InputDecoration(labelText: "Password"),
84. keyboardType: TextInputType.text,
85. obscureText: true,
86. controller: _passwordTextboxController,
87. validator: (value){
88. //jika karakter yang dimasukkan kurang dari 6 karakter
89. if(value.length < 6){
90. return "Password harus diisi minimal 6 karakter";
91. }
92. return null;
114
93. },
94. );
95. }
96.
97. //membuat textbox Konfirmasi Password
98. Widget _passwordKonfirmasiTextField() {
99. return TextFormField(
100. decoration: InputDecoration(labelText: "Konfirmasi Password"),
101. keyboardType: TextInputType.text,
102. obscureText: true,
103. validator: (value){
104. //jika inputan tidak sama dengan password
105. if(value != _passwordTextboxController.text) {
106. return "Konfirmasi Password tidak sama";
107. }
108. return null;
109. },
110. );
111. }
112.
113. //Membuat Tombol Registrasi
114. Widget _buttonRegistrasi() {
115. return RaisedButton(
116. child: Text("Registrasi"),
117. onPressed: (){
118. var validate = _formKey.currentState.validate();
119. });
120. }
121. }
Untuk mencoba halaman registrasi_page, buka file main.dart kemudian ubah kode menjadi
seperti berikut ini
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/ui/registrasi_page.dart';
3.
4. void main() {
5. runApp(MyApp());
6. }
7.
8. class MyApp extends StatefulWidget {
9. @override
10. _MyAppState createState() => _MyAppState();
11. }
12.
13. class _MyAppState extends State<MyApp> {
14.
15. @override
16. Widget build(BuildContext context) {
17. return MaterialApp(
18. title: 'Toko Kita',
19. debugShowCheckedModeBanner: false,
20. home: RegistrasiPage(),
21. );
22. }
23. }
115
b. Membuat Form Login
Buat sebuah file dengan nama login_page.dart pada folder ui dengan kode berikut
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/ui/registrasi_page.dart';
3.
4. class LoginPage extends StatefulWidget {
5. @override
6. _LoginPageState createState() => _LoginPageState();
7. }
8.
9. class _LoginPageState extends State<LoginPage> {
10. final _formKey = GlobalKey<FormState>();
11. bool _isLoading = false;
12.
13. final _emailTextboxController = TextEditingController();
14. final _passwordTextboxController = TextEditingController();
15.
16. @override
17. Widget build(BuildContext context) {
18. return Scaffold(
19. appBar: AppBar(title: Text("Login")),
20. body: SingleChildScrollView(
21. child: Container(
22. child: Padding(
23. padding: const EdgeInsets.all(8.0),
24. child: Form(
25. key: _formKey,
26. child: Column(
27. children: [
28. _emailTextField(),
116
29. _passwordTextField(),
30. _buttonLogin(),
31. SizedBox(height: 30,),
32. _menuRegistrasi()
33. ],
34. ),
35. ),
36. ),
37. ),
38. ),
39. );
40. }
41.
42. //Membuat Textbox email
43. Widget _emailTextField() {
44. return TextFormField(
45. decoration: InputDecoration(labelText: "Email"),
46. keyboardType: TextInputType.emailAddress,
47. controller: _emailTextboxController,
48. validator: (value){
49. //validasi harus diisi
50. if(value.isEmpty){
51. return 'Email harus diisi';
52. }
53. return null;
54. },
55. );
56. }
57.
58. //Membuat Textbox password
59. Widget _passwordTextField() {
60. return TextFormField(
61. decoration: InputDecoration(labelText: "Password"),
62. keyboardType: TextInputType.text,
63. obscureText: true,
64. controller: _passwordTextboxController,
65. validator: (value){
66. //validasi harus diisi
67. if(value.isEmpty){
68. return "Password harus diisi";
69. }
70. return null;
71. },
72. );
73. }
74.
75. //Membuat Tombol Login
76. Widget _buttonLogin() {
77. return RaisedButton(
78. child: Text("Login"),
79. onPressed: (){
80. var validate = _formKey.currentState.validate();
81. });
82. }
83.
84. // Membuat menu untuk membuka halaman registrasi
85. Widget _menuRegistrasi() {
86. return Container(
87. child: Center(
88. child: InkWell(
89. child: Text("Registrasi",style: TextStyle(color: Colors.blue),),
90. onTap: () {
91. Navigator.push(context, new MaterialPageRoute(builder: (context)=> Regis
trasiPage()));
92. },
117
93. ),
94. ),
95. );
96. }
97. }
Untuk mencobanya modifikasi file main.dart dimana pada bagian home akan memanggil
LoginPage()
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/ui/login_page.dart';
3.
4. void main() {
5. runApp(MyApp());
6. }
7.
8. class MyApp extends StatefulWidget {
9. @override
10. _MyAppState createState() => _MyAppState();
11. }
12.
13. class _MyAppState extends State<MyApp> {
14.
15. @override
16. Widget build(BuildContext context) {
17. return MaterialApp(
18. title: 'Toko Kita',
19. debugShowCheckedModeBanner: false,
20. home: LoginPage(),
21. );
22. }
23. }
Pada saat dijalankan akan terdapat link untuk membuka halaman registrasi pada bagian bawah
form
118
c. Membuat Form Produk
Form produk yang akan kita buat berikut ini memiliki 2 fungsi yaitu untuk menambah data
produk dan mengubah data produk
Buat sebuah file dengan nama produk_form.dart pada folder ui dengan kode berikut
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/model/produk.dart';
3.
4. class ProdukForm extends StatefulWidget {
5. Produk produk;
6. ProdukForm({this.produk});
7. @override
8. _ProdukFormState createState() => _ProdukFormState();
9. }
10.
11. class _ProdukFormState extends State<ProdukForm> {
12. final _formKey = GlobalKey<FormState>();
13. bool _isLoading = false;
14. String judul = "TAMBAH PRODUK";
15. String tombolSubmit = "SIMPAN";
16.
17. final _kodeProdukTextboxController = TextEditingController();
18. final _namaProdukTextboxController = TextEditingController();
19. final _hargaProdukTextboxController = TextEditingController();
20.
21. @override
22. void initState() {
23. // TODO: implement initState
24. super.initState();
119
25. isUpdate();
26. }
27.
28. isUpdate(){
29. if(widget.produk!=null){
30. setState(() {
31. judul = "UBAH PRODUK";
32. tombolSubmit = "UBAH";
33. _kodeProdukTextboxController.text = widget.produk.kodeProduk;
34. _namaProdukTextboxController.text = widget.produk.namaProduk;
35. _hargaProdukTextboxController.text = widget.produk.hargaProduk.toString();
36. });
37. }else{
38. judul = "TAMBAH PRODUK";
39. tombolSubmit = "SIMPAN";
40. }
41. }
42.
43. @override
44. Widget build(BuildContext context) {
45. return Scaffold(
46. appBar: AppBar(title: Text(judul)),
47. body: SingleChildScrollView(
48. child: Container(
49. child: Padding(
50. padding: const EdgeInsets.all(8.0),
51. child: Form(
52. key: _formKey,
53. child: Column(
54. children: [
55. _kodeProdukTextField(),
56. _namaProdukTextField(),
57. _hargaProdukTextField(),
58. _buttonSubmit()
59. ],
60. ),
61. ),
62. ),
63. ),
64. ),
65. );
66. }
67.
68. //Membuat Textbox Kode Produk
69. Widget _kodeProdukTextField() {
70. return TextFormField(
71. decoration: InputDecoration(labelText: "Kode Produk"),
72. keyboardType: TextInputType.text,
73. controller: _kodeProdukTextboxController,
74. validator: (value) {
75. if (value.isEmpty) {
76. return "Kode Produk harus diisi";
77. }
78. return null;
79. },
80. );
81. }
82.
83. //Membuat Textbox Nama Produk
84. Widget _namaProdukTextField() {
85. return TextFormField(
86. decoration: InputDecoration(labelText: "Nama Produk"),
87. keyboardType: TextInputType.text,
88. controller: _namaProdukTextboxController,
89. validator: (value) {
120
90. if (value.isEmpty) {
91. return "Nama Produk harus diisi";
92. }
93. return null;
94. },
95. );
96. }
97.
98. //Membuat Textbox Harga Produk
99. Widget _hargaProdukTextField() {
100. return TextFormField(
101. decoration: InputDecoration(labelText: "Harga"),
102. keyboardType: TextInputType.number,
103. controller: _hargaProdukTextboxController,
104. validator: (value) {
105. if (value.isEmpty) {
106. return "Harga harus diisi";
107. }
108. return null;
109. },
110. );
111. }
112.
113. //Membuat Tombol Simpan/Ubah
114. Widget _buttonSubmit() {
115. return RaisedButton(
116. child: Text(tombolSubmit),
117. onPressed: () {
118. var validate = _formKey.currentState.validate();
119. });
120. }
121. }
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/model/produk.dart';
3. import 'package:tokokita/ui/produk_form.dart';
4.
5. class ProdukDetail extends StatefulWidget {
6. Produk produk;
7. ProdukDetail({this.produk});
8. @override
9. _ProdukDetailState createState() => _ProdukDetailState();
10. }
11.
12. class _ProdukDetailState extends State<ProdukDetail> {
13. @override
14. Widget build(BuildContext context) {
15. return Scaffold(
16. appBar: AppBar(
17. title: Text('Detail Produk'),
18. ),
19. body: Center(
20. child: Column(
21. children: [
22. Text(
23. "Kode : ${widget.produk.kodeProduk}",
24. style: TextStyle(fontSize: 20.0),
121
25. ),
26. Text(
27. "Nama : ${widget.produk.namaProduk}",
28. style: TextStyle(fontSize: 18.0),
29. ),
30. Text(
31. "Harga : Rp. ${widget.produk.hargaProduk.toString()}",
32. style: TextStyle(fontSize: 18.0),
33. ),
34. _tombolHapusEdit()
35. ],
36. ),
37. ),
38. );
39. }
40.
41. Widget _tombolHapusEdit() {
42. return Row(
43. mainAxisSize: MainAxisSize.min,
44. children: [
45. //Tombol Edit
46. RaisedButton(
47. child: Text("EDIT"), color: Colors.green, onPressed: () {
48. Navigator.push(
49. context,
50. new MaterialPageRoute(
51. builder: (context) => ProdukForm(produk: widget.produk,)));
52. }),
53. //Tombol Hapus
54. RaisedButton(
55. child: Text("DELETE"), color: Colors.red, onPressed: ()=>confirmHapus())
,
56. ],
57. );
58. }
59.
60. void confirmHapus() {
61. AlertDialog alertDialog = new AlertDialog(
62. content: Text("Yakin ingin menghapus data ini?"),
63. actions: [
64. //tombol hapus
65. RaisedButton(
66. child: Text("Ya"),
67. color: Colors.green,
68. onPressed: (){},
69. ),
70. //tombol batal
71. RaisedButton(
72. child: Text("Batal"),
73. color: Colors.red,
74. onPressed: ()=>Navigator.pop(context),
75. )
76. ],
77. );
78.
79. showDialog(context: context, child: alertDialog);
80. }
81. }
1. import 'package:flutter/cupertino.dart';
122
2. import 'package:flutter/material.dart';
3. import 'package:tokokita/model/produk.dart';
4. import 'package:tokokita/ui/produk_detail.dart';
5. import 'package:tokokita/ui/produk_form.dart';
6.
7. class ProdukPage extends StatefulWidget {
8. @override
9. _ProdukPageState createState() => _ProdukPageState();
10. }
11.
12. class _ProdukPageState extends State<ProdukPage> {
13. @override
14. Widget build(BuildContext context) {
15. return Scaffold(
16. appBar: AppBar(
17. title: Text('List Produk'),
18. actions: [
19. Padding(
20. padding: EdgeInsets.only(right: 20.0),
21. child: GestureDetector(
22. child: Icon(Icons.add, size: 26.0),
23. onTap: () async {
24. Navigator.push(
25. context,
26. new MaterialPageRoute(
27. builder: (context) => ProdukForm()));
28. },
29. ))
30. ],
31. ),
32. drawer: Drawer(
33. child: ListView(
34. children: [
35. ListTile(
36. title: Text('Logout'),
37. trailing: Icon(Icons.logout),
38. onTap: () async {},
39. )
40. ],
41. ),
42. ),
43. body: ListView(
44. children: [
45. ItemProduk(produk: Produk(id: 1, kodeProduk: 'A001', namaProduk: 'Kamera',
hargaProduk: 5000000)),
46. ItemProduk(produk: Produk(id: 2, kodeProduk: 'A002', namaProduk: 'Kulkas',
hargaProduk: 2500000)),
47. ItemProduk(produk: Produk(id: 3, kodeProduk: 'A003', namaProduk: 'Mesin Cu
ci', hargaProduk: 2000000)),
48. ],
49. ),
50. );
51. }
52. }
53.
54. class ItemProduk extends StatelessWidget {
55. final Produk produk;
56.
57. ItemProduk({this.produk});
58.
59. @override
60. Widget build(BuildContext context) {
61. return Container(
62. child: GestureDetector(
63. onTap: () {
123
64. Navigator.push(
65. context,
66. new MaterialPageRoute(
67. builder: (context) => ProdukDetail(produk: produk,)));
68. },
69. child: Card(
70. child: ListTile(
71. title: Text(produk.namaProduk),
72. subtitle: Text(produk.hargaProduk.toString()),
73. ),
74. ),
75. ),
76. );
77. }
78. }
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/ui/produk_page.dart';
3.
4. void main() {
5. runApp(MyApp());
6. }
7.
8. class MyApp extends StatefulWidget {
9. @override
10. _MyAppState createState() => _MyAppState();
11. }
12.
13. class _MyAppState extends State<MyApp> {
14.
15. @override
16. Widget build(BuildContext context) {
17. return MaterialApp(
18. title: 'Toko Kita',
19. debugShowCheckedModeBanner: false,
20. home: ProdukPage(),
21. );
22. }
23. }
124
Pada saat tombol tambah diklik maka akan muncul form produk seperti berikut
125
Jika salah satu data produk diklik maka akan muncul detail produk
Ketika tombol EDIT diklik maka akan muncul form produk untuk mengubah data produk
126
Pada materi selanjutnya akan ada modifikasi pada tampil produk agar dapat menampilkan data
dari Rest API serta modifikasi pada Form Produk sehingga dapat berfungsi untuk menyimpan
ataupun mengubah data pada Rest API.
127
PERTEMUAN 10
Untuk mengunduh depedencies atau package yang telah ditambahkan, buka CommandPrompt
kemudian masuk ke folder projek dan ketikkan flutter pub get kemudian tekan Enter
128
Kemudian pada folder helpers buat sebuah file dengan nama user_info.dart dan masukkan
kode berikut
1. import 'package:shared_preferences/shared_preferences.dart';
2.
3. class UserInfo {
4. Future setToken(String value) async {
5. final SharedPreferences pref = await SharedPreferences.getInstance();
6. return pref.setString("token", value);
7. }
8.
9. Future<String> getToken() async {
10. final SharedPreferences pref = await SharedPreferences.getInstance();
129
11. return pref.getString("token");
12. }
13.
14. Future setUserID(int value) async {
15. final SharedPreferences pref = await SharedPreferences.getInstance();
16. return pref.setInt("userID", value);
17. }
18.
19. Future<int> getUserID() async {
20. final SharedPreferences pref = await SharedPreferences.getInstance();
21. return pref.getInt("userID");
22. }
23.
24. Future logout() async {
25. final SharedPreferences pref = await SharedPreferences.getInstance();
26. pref.clear();
27. }
28. }
c. Http request
Membuat Modul Error Handling
Buat sebuah file pada folder helpers dengan nama app_exception.dart kemudian
ketikkan kode berikut
130
Pada file ini berfungsi sebagai penanganan jika terjadi error saat melakukan
permintaan atau pengiriman ke Rest API
1. import 'dart:io';
2.
3. import 'package:http/http.dart' as http;
4. import 'package:tokokita/helpers/user_info.dart';
5. import 'app_exception.dart';
6.
7. class Api{
8. Future<dynamic> post(String url, dynamic data) async {
9. var token = await UserInfo().getToken();
10. var responseJson;
11. try {
12. final response = await http.post(url, body: data, headers: {
13. HttpHeaders.authorizationHeader: "Bearer $token"
14. });
15. responseJson = _returnResponse(response);
16. } on SocketException {
17. throw FetchDataException('No Internet connection');
18. }
19. return responseJson;
20. }
21.
22. Future<dynamic> get(String url) async {
23. var token = await UserInfo().getToken();
24. var responseJson;
25. try {
26. final response = await http.get(url, headers: {
27. HttpHeaders.authorizationHeader: "Bearer $token"
28. });
29. responseJson = _returnResponse(response);
30. } on SocketException {
31. throw FetchDataException('No Internet connection');
32. }
33. return responseJson;
34. }
35.
36. Future<dynamic> delete(String url) async {
37. var token = await UserInfo().getToken();
38. var responseJson;
39. try {
40. final response = await http.delete(url, headers: {
41. HttpHeaders.authorizationHeader: "Bearer $token"
42. });
43. responseJson = _returnResponse(response);
44. } on SocketException {
45. throw FetchDataException('No Internet connection');
46. }
47. return responseJson;
48. }
49.
131
50. dynamic _returnResponse(http.Response response) {
51. switch (response.statusCode) {
52. case 200:
53. return response;
54. case 400:
55. throw BadRequestException(response.body.toString());
56. case 401:
57. case 403:
58. throw UnauthorisedException(response.body.toString());
59. case 422:
60. throw InvalidInputException(response.body.toString());
61. case 500:
62. default:
63. throw FetchDataException(
64. 'Error occured while Communication with Server with StatusCode : ${respo
nse.statusCode}');
65. }
66. }
67. }
1. class ApiUrl {
2. static const String baseUrl = 'http://10.0.2.2/toko-api/public';
3.
4. static const String registrasi = baseUrl + '/registrasi';
5. static const String login = baseUrl + '/login';
6. static const String listProduk = baseUrl + '/produk';
7. static const String createProduk = baseUrl + '/produk';
8.
9. static String updateProduk(int id) {
10. return baseUrl + '/produk/' + id.toString() + '/update';
11. }
12.
13. static String showProduk(int id) {
14. return baseUrl + '/produk/' + id.toString();
15. }
16.
17. static String deleteProduk(int id) {
18. return baseUrl + '/produk/' + id.toString();
19. }
20. }
Pada baris kedua (baseUrl) merupakan alamat IP dari Rest API, untuk memeriksa apakah
terhubung dengan emulator atau tidak, dapat dilakukan dengan memasukkan alamat
tersebut pada browser yang ada pada emulator atau handphone android yang terkoneksi
dengan laptop
132
2. Membuat Bloc
Buat sebuah folder bernama bloc. Di dalam folder ini berisis file-file yang berfungsi sebagai
controller baik itu untuk melakukan proses login, registrasi dan lain-lain.
133
a. Registrasi
Buat sebuah file dengan nama registrasi_bloc.dart pada folder bloc. Kemudian masukkan kode
berikut
1. import 'dart:convert';
2.
3. import 'package:tokokita/helpers/api.dart';
4. import 'package:tokokita/helpers/api_url.dart';
5. import 'package:tokokita/model/registrasi.dart';
6.
7. class RegistrasiBloc{
8. static Future<Registrasi> registrasi({String nama, String email, String password})
async {
9. String apiUrl = ApiUrl.registrasi;
10.
11. var body = {
12. "nama": nama,
13. "email":email,
14. "password":password
15. };
16.
17. var response = await Api().post(apiUrl, body);
18. var jsonObj = json.decode(response.body);
19. return Registrasi.fromJson(jsonObj);
20. }
21. }
b. Login
Buat sebuah file dengan nama login_bloc.dart pada folder bloc. Kemudian masukkan kode
berikut
1. import 'dart:convert';
2.
3. import 'package:tokokita/helpers/api.dart';
4. import 'package:tokokita/helpers/api_url.dart';
5. import 'package:tokokita/model/login.dart';
6.
7. class LoginBloc{
8. static Future<Login> login({String email, String password}) async {
9. String apiUrl = ApiUrl.login;
10. var body = {"email": email, "password": password};
11. var response = await Api().post(apiUrl, body);
12. var jsonObj = json.decode(response.body);
13. return Login.fromJson(jsonObj);
14. }
15. }
c. Logout
Buat sebuah file dengan nama logout_bloc.dart pada folder bloc. Kemudian masukkan kode
berikut
1. import 'package:tokokita/helpers/user_info.dart';
2.
3. class LogoutBloc{
4. static Future logout() async {
5. await UserInfo().logout();
134
6. }
7. }
d. Produk
Pada bagian ini akan dibuat beberapa fungsi untuk mengambil, mengubah dan menghapus
data produk dari Rest API. Buat sebuah file dengan nama produk_bloc.dart pada folder bloc
kemudian masukkan kode berikut
1. import 'dart:convert';
2.
3. import 'package:tokokita/helpers/api.dart';
4. import 'package:tokokita/helpers/api_url.dart';
5. import 'package:tokokita/model/produk.dart';
6.
7. class ProdukBloc{
8. static Future<List<Produk>> getProduks() async {
9. String apiUrl = ApiUrl.listProduk;
10. var response = await Api().get(apiUrl);
11. var jsonObj = json.decode(response.body);
12. List<dynamic> listProduk = (jsonObj as Map<String, dynamic>)['data'];
13. List<Produk> produks = [];
14. for(int i=0; i < listProduk.length; i++){
15. produks.add(Produk.fromJson(listProduk[i]));
16. }
17. return produks;
18. }
19.
20. static Future addProduk({Produk produk}) async {
21. String apiUrl = ApiUrl.createProduk;
22.
23. var body = {
24. "kode_produk": produk.kodeProduk,
25. "nama_produk":produk.namaProduk,
26. "harga":produk.hargaProduk.toString()
27. };
28.
29. var response = await Api().post(apiUrl, body);
30. var jsonObj = json.decode(response.body);
31. return jsonObj['status'];
32. }
33.
34. static Future<bool> updateProduk({Produk produk}) async {
35. String apiUrl = ApiUrl.updateProduk(produk.id);
36.
37. var body = {
38. "kode_produk": produk.kodeProduk,
39. "nama_produk":produk.namaProduk,
40. "harga":produk.hargaProduk.toString()
41. };
42. print("Body : $body");
43. var response = await Api().post(apiUrl, body);
44. var jsonObj = json.decode(response.body);
45. return jsonObj['data'];
46. }
47.
48. static Future<bool> deleteProduk({int id}) async {
49. String apiUrl = ApiUrl.deleteProduk(id);
50.
51. var response = await Api().delete(apiUrl);
52. var jsonObj = json.decode(response.body);
53. return (jsonObj as Map<String, dynamic>)['data'];
135
54. }
55. }
56.
136
PERTEMUAN 11
1. Menyatukan Fungsionalitas
a. Membuat Common Dialog Widget
Pada bagian ini akan dibuat dua buah dialog yang nantinya akan digunakan pada tampilan. Buat
sebuah folder dengan nama widget
1. import 'package:flutter/material.dart';
2.
3. class Consts {
4. Consts._();
5.
6. static const double padding = 16.0;
7. static const double avatarRadius = 66.0;
8. }
9.
10. class SuccessDialog extends StatelessWidget {
137
11. final String description;
12. final VoidCallback okClick;
13.
14. SuccessDialog({this.description, this.okClick});
15.
16. @override
17. Widget build(BuildContext context) {
18. return Dialog(
19. shape: RoundedRectangleBorder(
20. borderRadius: BorderRadius.circular(Consts.padding)),
21. elevation: 0.0,
22. backgroundColor: Colors.transparent,
23. child: dialogContent(context),
24. );
25. }
26.
27. dialogContent(BuildContext context) {
28. return Container(
29. padding: EdgeInsets.only(
30. top: Consts.padding,
31. bottom: Consts.padding,
32. left: Consts.padding,
33. right: Consts.padding,
34. ),
35. margin: EdgeInsets.only(top: Consts.avatarRadius),
36. decoration: new BoxDecoration(
37. color: Colors.white,
38. shape: BoxShape.rectangle,
39. borderRadius: BorderRadius.circular(Consts.padding),
40. boxShadow: [
41. BoxShadow(
42. color: Colors.black26,
43. blurRadius: 10.0,
44. offset: const Offset(0.0, 10.0),
45. ),
46. ],
47. ),
48. child: Column(
49. mainAxisSize: MainAxisSize.min,
50. children: [
51. Text(
52. "SUKSES",
53. style: TextStyle(
54. fontSize: 24.0,
55. fontWeight: FontWeight.w700,
56. color: Colors.green),
57. ),
58. SizedBox(height: 16.0),
59. Text(
60. description,
61. textAlign: TextAlign.center,
62. style: TextStyle(
63. fontSize: 16.0,
64. ),
65. ),
66. SizedBox(height: 24.0),
67. Align(
68. alignment: Alignment.bottomRight,
69. child: FlatButton(
70. onPressed: () {
71. Navigator.of(context).pop(); // To close the dialog
72. okClick();
73. },
74. child: Text("OK"),
75. ),
138
76. )
77. ],
78. ),
79. );
80. }
81. }
1. import 'package:flutter/material.dart';
2.
3. class Consts {
4. Consts._();
5.
6. static const double padding = 16.0;
7. static const double avatarRadius = 66.0;
8. }
9.
10. class WarningDialog extends StatelessWidget {
11. final String description;
12. final VoidCallback okClick;
13.
14. WarningDialog({this.description, this.okClick});
15.
16. @override
17. Widget build(BuildContext context) {
18. return Dialog(
19. shape: RoundedRectangleBorder(
20. borderRadius: BorderRadius.circular(Consts.padding)),
21. elevation: 0.0,
22. backgroundColor: Colors.transparent,
23. child: dialogContent(context),
24. );
25. }
26.
27. dialogContent(BuildContext context) {
28. return Container(
29. padding: EdgeInsets.only(
30. top: Consts.padding,
31. bottom: Consts.padding,
32. left: Consts.padding,
33. right: Consts.padding,
34. ),
35. margin: EdgeInsets.only(top: Consts.avatarRadius),
36. decoration: new BoxDecoration(
37. color: Colors.white,
38. shape: BoxShape.rectangle,
39. borderRadius: BorderRadius.circular(Consts.padding),
40. boxShadow: [
41. BoxShadow(
42. color: Colors.black26,
43. blurRadius: 10.0,
44. offset: const Offset(0.0, 10.0),
45. ),
46. ],
47. ),
48. child: Column(
49. mainAxisSize: MainAxisSize.min,
50. children: [
51. Text(
52. "GAGAL",
53. style: TextStyle(
54. fontSize: 24.0, fontWeight: FontWeight.w700, color: Colors.red),
55. ),
139
56. SizedBox(height: 16.0),
57. Text(
58. description,
59. textAlign: TextAlign.center,
60. style: TextStyle(
61. fontSize: 16.0,
62. ),
63. ),
64. SizedBox(height: 24.0),
65. Align(
66. alignment: Alignment.bottomRight,
67. child: FlatButton(
68. onPressed: () {
69. Navigator.of(context).pop(); // To close the dialog
70. okClick();
71. },
72. child: Text("OK"),
73. ),
74. )
75. ],
76. ),
77. );
78. }
79. }
b. Modifikasi main.dart
Buka kembali file main.dart kita akan memodifikasi file tersebut dengan kondisi jika belum login
maka akan membuka halaman login, namun jika sudah login maka akan membuka halaman list
produk
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/helpers/user_info.dart';
3. import 'package:tokokita/ui/login_page.dart';
4. import 'package:tokokita/ui/produk_page.dart';
5.
6. void main() {
7. runApp(MyApp());
8. }
9.
10. class MyApp extends StatefulWidget {
11. @override
12. _MyAppState createState() => _MyAppState();
13. }
14.
15. class _MyAppState extends State<MyApp> {
16. Widget page = CircularProgressIndicator();
17.
18. @override
19. void initState() {
20. super.initState();
21. isLogin();
22. }
23.
24. void isLogin() async {
25. var token = await UserInfo().getToken();
26. if(token!=null){
27. setState(() {
28. page = ProdukPage();
140
29. });
30. }else{
31. setState(() {
32. page = LoginPage();
33. });
34. }
35. }
36.
37. @override
38. Widget build(BuildContext context) {
39. return MaterialApp(
40. title: 'Toko Kita',
41. debugShowCheckedModeBanner: false,
42. home: page,
43. );
44. }
45. }
c. Modifikasi registrasi_page.dart
Buka file registrasi_page.dart pada folder ui kemudian modifikasi fungsi _buttonRegistrasi dan
tambahkan fungsi dengan nama _submit seperti dibawah
141
156. });
157. setState(() {
158. _isLoading = false;
159. });
160. }
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/bloc/registrasi_bloc.dart';
3. import 'package:tokokita/widget/success_dialog.dart';
4. import 'package:tokokita/widget/warning_dialog.dart';
5.
6. class RegistrasiPage extends StatefulWidget {
7. @override
8. _RegistrasiPageState createState() => _RegistrasiPageState();
9. }
10.
11. class _RegistrasiPageState extends State<RegistrasiPage> {
12. final _formKey = GlobalKey<FormState>();
13. bool _isLoading = false;
14.
15. final _namaTextboxController = TextEditingController();
16. final _emailTextboxController = TextEditingController();
17. final _passwordTextboxController = TextEditingController();
18.
19. @override
20. Widget build(BuildContext context) {
21. return Scaffold(
22. appBar: AppBar(title: Text("Registrasi"),),
23. body: SingleChildScrollView(
24. child: Container(
25. child: Padding(
26. padding: const EdgeInsets.all(8.0),
27. child: Form(
28. key: _formKey,
29. child: Column(
30. mainAxisAlignment: MainAxisAlignment.center,
31. children: [
32. _namaTextField(),
33. _emailTextField(),
34. _passwordTextField(),
35. _passwordKonfirmasiTextField(),
36. _buttonRegistrasi()
37. ],
38. ),
39. ),
40. ),
41. ),
42. ),
43. );
44. }
45.
46. //Membuat Textbox Nama
47. Widget _namaTextField() {
48. return TextFormField(
49. decoration: InputDecoration(labelText: "Nama"),
50. keyboardType: TextInputType.text,
51. controller: _namaTextboxController,
52. validator: (value){
53. if(value.length < 3){
142
54. return "Nama harus diisi minimal 3 karakter";
55. }
56. return null;
57. },
58. );
59. }
60.
61. //Membuat Textbox email
62. Widget _emailTextField() {
63. return TextFormField(
64. decoration: InputDecoration(labelText: "Email"),
65. keyboardType: TextInputType.emailAddress,
66. controller: _emailTextboxController,
67. validator: (value){
68. //validasi harus diisi
69. if(value.isEmpty){
70. return 'Email harus diisi';
71. }
72. //validasi email
73. Pattern pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\
".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-
9]+\.)+[a-zA-Z]{2,}))$';
74. RegExp regex = new RegExp(pattern);
75. if (!regex.hasMatch(value)) {
76. return "Email tidak valid";
77. }
78. return null;
79. },
80. );
81. }
82.
83. //Membuat Textbox password
84. Widget _passwordTextField() {
85. return TextFormField(
86. decoration: InputDecoration(labelText: "Password"),
87. keyboardType: TextInputType.text,
88. obscureText: true,
89. controller: _passwordTextboxController,
90. validator: (value){
91. //jika karakter yang dimasukkan kurang dari 6 karakter
92. if(value.length < 6){
93. return "Password harus diisi minimal 6 karakter";
94. }
95. return null;
96. },
97. );
98. }
99.
100. //membuat textbox Konfirmasi Password
101. Widget _passwordKonfirmasiTextField() {
102. return TextFormField(
103. decoration: InputDecoration(labelText: "Konfirmasi Password"),
104. keyboardType: TextInputType.text,
105. obscureText: true,
106. validator: (value){
107. //jika inputan tidak sama dengan password
108. if(value != _passwordTextboxController.text) {
109. return "Konfirmasi Password tidak sama";
110. }
111. return null;
112. },
113. );
114. }
115.
116. //Membuat Tombol Registrasi
143
117. Widget _buttonRegistrasi() {
118. return RaisedButton(
119. child: Text("Registrasi"),
120. onPressed: (){
121. var validate = _formKey.currentState.validate();
122. if(validate) {
123. if(!_isLoading) _submit();
124. }
125. });
126. }
127.
128. void _submit() {
129. _formKey.currentState.save();
130. setState(() {
131. _isLoading = true;
132. });
133. RegistrasiBloc.registrasi(
134. nama: _namaTextboxController.text,
135. email: _emailTextboxController.text,
136. password: _passwordTextboxController.text
137. ).then((value) {
138. showDialog(
139. context: context,
140. barrierDismissible: false,
141. builder: (BuildContext context) => SuccessDialog(
142. description: "Registrasi berhasil, silahkan login",
143. okClick: () {
144. Navigator.pop(context);
145. },
146. )
147. );
148. }, onError: (error){
149. print(error);
150. showDialog(
151. context: context,
152. barrierDismissible: false,
153. builder: (BuildContext context) => WarningDialog(
154. description: "Registrasi gagal, silahkan coba lagi",
155. )
156. );
157. });
158. setState(() {
159. _isLoading = false;
160. });
161. }
162. }
144
d. Modifikasi login_page.dart (fungsi login)
Buka file login_page.dart pada folder ui kemudian modifikasi fungsi _buttonLogin dan
tambahkan fungsi dengan nama _submit seperti dibawah
145
108. barrierDismissible: false,
109. builder: (BuildContext context) => WarningDialog(
110. description: "Login gagal, silahkan coba lagi",
111. )
112. );
113. });
114. setState(() {
115. _isLoading = false;
116. });
117. }
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/bloc/login_bloc.dart';
3. import 'package:tokokita/helpers/user_info.dart';
4. import 'package:tokokita/ui/produk_page.dart';
5. import 'package:tokokita/ui/registrasi_page.dart';
6. import 'package:tokokita/widget/warning_dialog.dart';
7.
8. class LoginPage extends StatefulWidget {
9. @override
10. _LoginPageState createState() => _LoginPageState();
11. }
12.
13. class _LoginPageState extends State<LoginPage> {
14. final _formKey = GlobalKey<FormState>();
15. bool _isLoading = false;
16.
17. final _emailTextboxController = TextEditingController();
18. final _passwordTextboxController = TextEditingController();
19.
20. @override
21. Widget build(BuildContext context) {
22. return Scaffold(
23. appBar: AppBar(title: Text("Login")),
24. body: SingleChildScrollView(
25. child: Container(
26. child: Padding(
27. padding: const EdgeInsets.all(8.0),
28. child: Form(
29. key: _formKey,
30. child: Column(
31. children: [
32. _emailTextField(),
33. _passwordTextField(),
34. _buttonLogin(),
35. SizedBox(height: 30,),
36. _menuRegistrasi()
37. ],
38. ),
39. ),
40. ),
41. ),
42. ),
43. );
44. }
45.
46. //Membuat Textbox email
47. Widget _emailTextField() {
48. return TextFormField(
49. decoration: InputDecoration(labelText: "Email"),
50. keyboardType: TextInputType.emailAddress,
51. controller: _emailTextboxController,
146
52. validator: (value){
53. //validasi harus diisi
54. if(value.isEmpty){
55. return 'Email harus diisi';
56. }
57. return null;
58. },
59. );
60. }
61.
62. //Membuat Textbox password
63. Widget _passwordTextField() {
64. return TextFormField(
65. decoration: InputDecoration(labelText: "Password"),
66. keyboardType: TextInputType.text,
67. obscureText: true,
68. controller: _passwordTextboxController,
69. validator: (value){
70. //jika karakter yang dimasukkan kurang dari 6 karakter
71. if(value.isEmpty){
72. return "Password harus diisi";
73. }
74. return null;
75. },
76. );
77. }
78.
79. //Membuat Tombol Login
80. Widget _buttonLogin() {
81. return RaisedButton(
82. child: Text("Login"),
83. onPressed: (){
84. var validate = _formKey.currentState.validate();
85. if(validate) {
86. if(!_isLoading) _submit();
87. }
88. });
89. }
90.
91. void _submit() {
92. _formKey.currentState.save();
93. setState(() {
94. _isLoading = true;
95. });
96. LoginBloc.login(
97. email: _emailTextboxController.text,
98. password: _passwordTextboxController.text
99. ).then((value) async{
100. await UserInfo().setToken(value.token);
101. await UserInfo().setUserID(value.userID);
102. Navigator.pushReplacement(
103. context, new MaterialPageRoute(builder: (context) => ProdukPage())
);
104. }, onError: (error){
105. print(error);
106. showDialog(
107. context: context,
108. barrierDismissible: false,
109. builder: (BuildContext context) => WarningDialog(
110. description: "Login gagal, silahkan coba lagi",
111. )
112. );
113. });
114. setState(() {
115. _isLoading = false;
147
116. });
117. }
118.
119. // Membuat menu untuk membuka halaman registrasi
120. Widget _menuRegistrasi() {
121. return Container(
122. child: Center(
123. child: InkWell(
124. child: Text("Registrasi",style: TextStyle(color: Colors.blue),),
125. onTap: () {
126. Navigator.push(context, new MaterialPageRoute(builder: (context)
=> RegistrasiPage()));
127. },
128. ),
129. ),
130. );
131. }
132. }
148
149
PERTEMUAN 12
1. Modifikasi produk_page.dart
a. Menambahkan fungsi logout pada drawer
Agar link logout dapat berfungsi, akan ditambahkan kode pada drawer logout, seperti
berikut
1. import 'package:flutter/cupertino.dart';
2. import 'package:flutter/material.dart';
3. import 'package:tokokita/bloc/logout_bloc.dart';
4. import 'package:tokokita/model/produk.dart';
5. import 'package:tokokita/ui/login_page.dart';
6. import 'package:tokokita/ui/produk_detail.dart';
7. import 'package:tokokita/ui/produk_form.dart';
8.
9. class ProdukPage extends StatefulWidget {
10. @override
11. _ProdukPageState createState() => _ProdukPageState();
12. }
13.
14. class _ProdukPageState extends State<ProdukPage> {
15. @override
16. Widget build(BuildContext context) {
17. return Scaffold(
18. appBar: AppBar(
19. title: Text('List Produk'),
20. actions: [
21. Padding(
22. padding: EdgeInsets.only(right: 20.0),
23. child: GestureDetector(
24. child: Icon(Icons.add, size: 26.0),
25. onTap: () async {
26. Navigator.push(
27. context,
28. new MaterialPageRoute(
150
29. builder: (context) => ProdukForm()));
30. },
31. ))
32. ],
33. ),
34. drawer: Drawer(
35. child: ListView(
36. children: [
37. ListTile(
38. title: Text('Logout'),
39. trailing: Icon(Icons.logout),
40. onTap: () async {
41. await LogoutBloc.logout().then((value) {
42. Navigator.pushReplacement(context, new MaterialPageRoute(builder:
(context) => LoginPage()));
43. });
44. },
45. )
46. ],
47. ),
48. ),
49. body: ListView(
50. children: [
51. ItemProduk(produk: Produk(id: 1, kodeProduk: 'A001', namaProduk: 'Kamera',
hargaProduk: 5000000)),
52. ItemProduk(produk: Produk(id: 2, kodeProduk: 'A002', namaProduk: 'Kulkas',
hargaProduk: 2500000)),
53. ItemProduk(produk: Produk(id: 3, kodeProduk: 'A003', namaProduk: 'Mesin Cu
ci', hargaProduk: 2000000)),
54. ],
55. ),
56. );
57. }
58. }
59.
60. class ItemProduk extends StatelessWidget {
61. final Produk produk;
62.
63. ItemProduk({this.produk});
64.
65. @override
66. Widget build(BuildContext context) {
67. return Container(
68. child: GestureDetector(
69. onTap: () {
70. Navigator.push(
71. context,
72. new MaterialPageRoute(
73. builder: (context) => ProdukDetail(produk: produk,)));
74. },
75. child: Card(
76. child: ListTile(
77. title: Text(produk.namaProduk),
78. subtitle: Text(produk.hargaProduk.toString()),
79. ),
80. ),
81. ),
82. );
83. }
84. }
151
b. Menampilkan Data Produk dari Rest API
Pada bagian ini akan dimodifikasi file produk_page.dart sehingga dapat menampilkan data
dari Rest API. Berikut kode keseluruhan
1. import 'package:flutter/cupertino.dart';
2. import 'package:flutter/material.dart';
3. import 'package:tokokita/bloc/logout_bloc.dart';
4. import 'package:tokokita/bloc/produk_bloc.dart';
5. import 'package:tokokita/model/produk.dart';
6. import 'package:tokokita/ui/login_page.dart';
7. import 'package:tokokita/ui/produk_detail.dart';
8. import 'package:tokokita/ui/produk_form.dart';
9.
10. class ProdukPage extends StatefulWidget {
11. @override
12. _ProdukPageState createState() => _ProdukPageState();
13. }
14.
15. class _ProdukPageState extends State<ProdukPage> {
16. @override
17. Widget build(BuildContext context) {
18. return Scaffold(
19. appBar: AppBar(
20. title: Text('List Produk'),
21. actions: [
22. Padding(
23. padding: EdgeInsets.only(right: 20.0),
24. child: GestureDetector(
25. child: Icon(Icons.add, size: 26.0),
26. onTap: () async {
27. Navigator.push(
28. context,
29. new MaterialPageRoute(
30. builder: (context) => ProdukForm()));
31. },
32. ))
33. ],
34. ),
35. drawer: Drawer(
36. child: ListView(
37. children: [
38. ListTile(
39. title: Text('Logout'),
40. trailing: Icon(Icons.logout),
41. onTap: () async {
42. await LogoutBloc.logout().then((value) {
43. Navigator.pushReplacement(context, new MaterialPageRoute(builder:
(context) => LoginPage()));
44. });
45. },
46. )
47. ],
48. ),
49. ),
50. body: FutureBuilder<List>(
51. future: ProdukBloc.getProduks(),
52. builder: (context, snapshot){
53. if(snapshot.hasError) print(snapshot.error);
54. return snapshot.hasData ? ListProduk(list: snapshot.data,) : Center(child:
CircularProgressIndicator(),);
55. },
56. ),
152
57. );
58. }
59. }
60.
61. class ListProduk extends StatelessWidget {
62. final List list;
63. ListProduk({this.list});
64.
65. @override
66. Widget build(BuildContext context) {
67. return ListView.builder(
68. itemCount: list==null ? 0:list.length,
69. itemBuilder: (context, i){
70. return ItemProduk(produk: list[i],);
71. });
72. }
73. }
74.
75.
76. class ItemProduk extends StatelessWidget {
77. final Produk produk;
78.
79. ItemProduk({this.produk});
80.
81. @override
82. Widget build(BuildContext context) {
83. return Container(
84. child: GestureDetector(
85. onTap: () {
86. Navigator.push(
87. context,
88. new MaterialPageRoute(
89. builder: (context) => ProdukDetail(produk: produk,)));
90. },
91. child: Card(
92. child: ListTile(
93. title: Text(produk.namaProduk),
94. subtitle: Text(produk.hargaProduk.toString()),
95. ),
96. ),
97. ),
98. );
99. }
100. }
Adapun perubahan yang dilakukan adalah penambahan sebuah class bernama ListProduk
dengan kode
153
73. }
1. import 'package:flutter/cupertino.dart';
2. import 'package:flutter/material.dart';
3. import 'package:tokokita/bloc/logout_bloc.dart';
4. import 'package:tokokita/bloc/produk_bloc.dart';
5. import 'package:tokokita/model/produk.dart';
6. import 'package:tokokita/ui/login_page.dart';
7. import 'package:tokokita/ui/produk_detail.dart';
8. import 'package:tokokita/ui/produk_form.dart';
154
2. Memodifikasi Form Produk (produk_form.dart)
a. Membuat fungsi simpan
Agar tombol simpan dapat berfungsi diperlukan kode fungsi untuk menyimpan data
dengan memanggil bloc produk_bloc yang telah dibuat sebelumnya, kita akan
menambahkan sebuah fungsi dengan nama simpan dan memodifikasi fungsi
_buttonSubmit
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/bloc/produk_bloc.dart';
155
3. import 'package:tokokita/model/produk.dart';
4. import 'package:tokokita/ui/produk_page.dart';
5. import 'package:tokokita/widget/warning_dialog.dart';
6.
7. class ProdukForm extends StatefulWidget {
8. Produk produk;
9. ProdukForm({this.produk});
10. @override
11. _ProdukFormState createState() => _ProdukFormState();
12. }
13.
14. class _ProdukFormState extends State<ProdukForm> {
15. final _formKey = GlobalKey<FormState>();
16. bool _isLoading = false;
17. String judul = "TAMBAH PRODUK";
18. String tombolSubmit = "SIMPAN";
19.
20. final _kodeProdukTextboxController = TextEditingController();
21. final _namaProdukTextboxController = TextEditingController();
22. final _hargaProdukTextboxController = TextEditingController();
23.
24. @override
25. void initState() {
26. // TODO: implement initState
27. super.initState();
28. isUpdate();
29. }
30.
31. isUpdate(){
32. if(widget.produk!=null){
33. setState(() {
34. judul = "UBAH PRODUK";
35. tombolSubmit = "UBAH";
36. _kodeProdukTextboxController.text = widget.produk.kodeProduk;
37. _namaProdukTextboxController.text = widget.produk.namaProduk;
38. _hargaProdukTextboxController.text = widget.produk.hargaProduk.toString();
39. });
40. }else{
41. judul = "TAMBAH PRODUK";
42. tombolSubmit = "SIMPAN";
43. }
44. }
45.
46. @override
47. Widget build(BuildContext context) {
48. return Scaffold(
49. appBar: AppBar(title: Text(judul)),
50. body: SingleChildScrollView(
51. child: Container(
52. child: Padding(
53. padding: const EdgeInsets.all(8.0),
54. child: Form(
55. key: _formKey,
56. child: Column(
57. children: [
58. _kodeProdukTextField(),
59. _namaProdukTextField(),
60. _hargaProdukTextField(),
61. _buttonSubmit()
62. ],
63. ),
64. ),
65. ),
66. ),
67. ),
156
68. );
69. }
70.
71. //Membuat Textbox Kode Produk
72. Widget _kodeProdukTextField() {
73. return TextFormField(
74. decoration: InputDecoration(labelText: "Kode Produk"),
75. keyboardType: TextInputType.text,
76. controller: _kodeProdukTextboxController,
77. validator: (value) {
78. if (value.isEmpty) {
79. return "Kode Produk harus diisi";
80. }
81. return null;
82. },
83. );
84. }
85.
86. //Membuat Textbox Nama Produk
87. Widget _namaProdukTextField() {
88. return TextFormField(
89. decoration: InputDecoration(labelText: "Nama Produk"),
90. keyboardType: TextInputType.text,
91. controller: _namaProdukTextboxController,
92. validator: (value) {
93. if (value.isEmpty) {
94. return "Nama Produk harus diisi";
95. }
96. return null;
97. },
98. );
99. }
100.
101. //Membuat Textbox Harga Produk
102. Widget _hargaProdukTextField() {
103. return TextFormField(
104. decoration: InputDecoration(labelText: "Harga"),
105. keyboardType: TextInputType.number,
106. controller: _hargaProdukTextboxController,
107. validator: (value) {
108. if (value.isEmpty) {
109. return "Harga harus diisi";
110. }
111. return null;
112. },
113. );
114. }
115.
116. //Membuat Tombol Simpan/Ubah
117. Widget _buttonSubmit() {
118. return RaisedButton(
119. child: Text(tombolSubmit),
120. onPressed: () {
121. var validate = _formKey.currentState.validate();
122. if(validate) {
123. if(!_isLoading){
124. if(widget.produk!=null){
125. //kondisi update produk
126.
127. }else{
128. //kondisi tambah produk
129. simpan();
130. }
131. }
132. }
157
133. });
134. }
135.
136. simpan() {
137. setState(() {
138. _isLoading = true;
139. });
140. Produk createProduk = new Produk();
141. createProduk.kodeProduk = _kodeProdukTextboxController.text;
142. createProduk.namaProduk = _namaProdukTextboxController.text;
143. createProduk.hargaProduk = int.parse(_hargaProdukTextboxController.text)
;
144. ProdukBloc.addProduk(produk: createProduk).then((value) {
145. Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContex
t context) => ProdukPage()));
146. },onError: (error){
147. showDialog(
148. context: context,
149. builder: (BuildContext context) => WarningDialog(
150. description: "Simpan gagal, silahkan coba lagi",
151. )
152. );
153. });
154. setState(() {
155. _isLoading = false;
156. });
157. }
158. }
159. ubah() {
160. setState(() {
161. _isLoading = true;
162. });
163. Produk updateProduk = new Produk();
164. updateProduk.id = widget.produk.id;
165. updateProduk.kodeProduk = _kodeProdukTextboxController.text;
166. updateProduk.namaProduk = _namaProdukTextboxController.text;
167. updateProduk.hargaProduk = int.parse(_hargaProdukTextboxController.text);
168. ProdukBloc.updateProduk(produk: updateProduk).then((value) {
169. Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)
=> ProdukPage()));
170. },onError: (error){
171. showDialog(
172. context: context,
173. builder: (BuildContext context) => WarningDialog(
174. description: "Permintaan ubah data gagal, silahkan coba lagi",
175. )
176. );
177. });
178. setState(() {
179. _isLoading = false;
158
180. });
181. }
160
231. },
232. );
233. }
234.
235. //Membuat Textbox Harga Produk
236. Widget _hargaProdukTextField() {
237. return TextFormField(
238. decoration: InputDecoration(labelText: "Harga"),
239. keyboardType: TextInputType.number,
240. controller: _hargaProdukTextboxController,
241. validator: (value) {
242. if (value.isEmpty) {
243. return "Harga harus diisi";
244. }
245. return null;
246. },
247. );
248. }
249.
250. //Membuat Tombol Simpan/Ubah
251. Widget _buttonSubmit() {
252. return RaisedButton(
253. child: Text(tombolSubmit),
254. onPressed: () {
255. var validate = _formKey.currentState.validate();
256. if(validate) {
257. if(!_isLoading){
258. if(widget.produk!=null){
259. //kondisi update produk
260. ubah();
261. }else{
262. //kondisi tambah produk
263. simpan();
264. }
265. }
266. }
267. });
268. }
269.
270. simpan() {
271. setState(() {
272. _isLoading = true;
273. });
274. Produk createProduk = new Produk();
275. createProduk.kodeProduk = _kodeProdukTextboxController.text;
276. createProduk.namaProduk = _namaProdukTextboxController.text;
277. createProduk.hargaProduk = int.parse(_hargaProdukTextboxController.text);
278. ProdukBloc.addProduk(produk: createProduk).then((value) {
279. Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext contex
t) => ProdukPage()));
280. },onError: (error){
281. showDialog(
282. context: context,
283. builder: (BuildContext context) => WarningDialog(
284. description: "Simpan gagal, silahkan coba lagi",
285. )
286. );
287. });
288. setState(() {
289. _isLoading = false;
290. });
291. }
292.
293. ubah() {
294. setState(() {
161
295. _isLoading = true;
296. });
297. Produk updateProduk = new Produk();
298. updateProduk.id = widget.produk.id;
299. updateProduk.kodeProduk = _kodeProdukTextboxController.text;
300. updateProduk.namaProduk = _namaProdukTextboxController.text;
301. updateProduk.hargaProduk = int.parse(_hargaProdukTextboxController.text);
302. ProdukBloc.updateProduk(produk: updateProduk).then((value) {
303. Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext contex
t) => ProdukPage()));
304. },onError: (error){
305. showDialog(
306. context: context,
307. builder: (BuildContext context) => WarningDialog(
308. description: "Permintaan ubah data gagal, silahkan coba lagi",
309. )
310. );
311. });
312. setState(() {
313. _isLoading = false;
314. });
315. }
316. }
162
93. showDialog(context: context, child: alertDialog);
94. }
1. import 'package:flutter/material.dart';
2. import 'package:tokokita/bloc/produk_bloc.dart';
3. import 'package:tokokita/model/produk.dart';
4. import 'package:tokokita/ui/produk_form.dart';
5. import 'package:tokokita/ui/produk_page.dart';
6. import 'package:tokokita/widget/warning_dialog.dart';
7.
8. class ProdukDetail extends StatefulWidget {
9. Produk produk;
10. ProdukDetail({this.produk});
11. @override
12. _ProdukDetailState createState() => _ProdukDetailState();
13. }
14.
15. class _ProdukDetailState extends State<ProdukDetail> {
16. @override
17. Widget build(BuildContext context) {
18. return Scaffold(
19. appBar: AppBar(
20. title: Text('Detail Produk'),
21. ),
22. body: Center(
23. child: Column(
24. children: [
25. Text(
26. "Kode : ${widget.produk.kodeProduk}",
27. style: TextStyle(fontSize: 20.0),
28. ),
29. Text(
30. "Nama : ${widget.produk.namaProduk}",
31. style: TextStyle(fontSize: 18.0),
32. ),
33. Text(
34. "Harga : Rp. ${widget.produk.hargaProduk.toString()}",
35. style: TextStyle(fontSize: 18.0),
36. ),
37. _tombolHapusEdit()
38. ],
39. ),
40. ),
41. );
42. }
43.
44. Widget _tombolHapusEdit() {
45. return Row(
46. mainAxisSize: MainAxisSize.min,
47. children: [
48. //Tombol Edit
49. RaisedButton(
50. child: Text("EDIT"), color: Colors.green, onPressed: () {
51. Navigator.push(
52. context,
53. new MaterialPageRoute(
54. builder: (context) => ProdukForm(produk: widget.produk,)));
163
55. }),
56. //Tombol Hapus
57. RaisedButton(
58. child: Text("DELETE"), color: Colors.red, onPressed: ()=>confirmHapus()),
59. ],
60. );
61. }
62.
63. void confirmHapus() {
64. AlertDialog alertDialog = new AlertDialog(
65. content: Text("Yakin ingin menghapus data ini?"),
66. actions: [
67. //tombol hapus
68. RaisedButton(
69. child: Text("Ya"),
70. color: Colors.green,
71. onPressed: (){
72. ProdukBloc.deleteProduk(id: widget.produk.id).then((value){
73. Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext c
ontext) => ProdukPage()));
74. },onError: (error){
75. showDialog(
76. context: context,
77. builder: (BuildContext context) => WarningDialog(
78. description: "Hapus data gagal, silahkan coba lagi",
79. )
80. );
81. });
82. },
83. ),
84. //tombol batal
85. RaisedButton(
86. child: Text("Batal"),
87. color: Colors.red,
88. onPressed: ()=>Navigator.pop(context),
89. )
90. ],
91. );
92.
93. showDialog(context: context, child: alertDialog);
94. }
95. }
164
PERTEMUAN 13-15
Pada pertemuan ini mahasiswa melakukan presentasi terhadap projek yang telah dihasilkan
dan dikembangkan dari modul sebagai hasil dari nilai UAS.
165