Home Android CRUD with FireBase Part 2

CRUD with FireBase Part 2

0
CRUD with FireBase Part 2

Halo teman – teman, karena sebelumnya kita sudah menghubungkan project dengan Firebase sebagai database (realtime database). Kali ini kita akan membangun CRUD dengan memanfaatkan realtime database ini.

Jadi pertama kita perlu menyiapkan file model yang berfungsi sebagai jembatan sebagai get, post dan update data. Sebelum itu, kita memerlukan file berikut pada direktori lib

Kenapa file nya di kelompokkan ke dalam folder? Ini bertujuan agar memudahkan dalam pembacaan kode serta mudah jika kita mengerjakan suatu project dalam kelompok atau singkatnya lebih mudah di pahami. Dengen mengelompokkan nya maka kita akan tau lebih cepat oh, ini file untuk ui.

Baik, lanjut ke model yang akan kita buat, di sini saya memberi nama file nya databrg.dart karena bertujuan untuk CRUD Data Barang itu sendiri

import 'package:firebase_database/firebase_database.dart';

class Barang {
  final String? key;
  String? namaBrg;
  bool? favorite;
  String? price;
  String? stock;
  String? desc;

  Barang(
      {this.key,
      this.namaBrg,
      this.favorite,
      this.price,
      this.stock,
      this.desc});

  Barang.fromSnapshot(DataSnapshot snapshot) : key = snapshot.key,   //proses sending data ke realtime database
        namaBrg = snapshot.value['namaBrg'],
        favorite = snapshot.value['favorite'],
        price = snapshot.value['price'],
        stock = snapshot.value['stock'],
        desc = snapshot.value['desc'];

  Map<String, dynamic> toJson() => {  //agar data dapat di baca dari bentuk Array ke bentuk JSON, karena flutter
    'namaBrg' : namaBrg,              //hanya dapat membaca data dalam bentuk JSON
    'favorite' : favorite,
    'price' : price,
    'stock' : stock,
    'desc' : desc,
  };

}

Selanjutnya kita akan membuat file home_page.dart yang nantinya akan berfungsi menampilkan data sekaligus di sini kita juga akan menggunakan pop up untuk menambahkan data. Dan memanfaatkan Dismissible untuk menghapus data dengan slide ke kiri ataupun kanan

import 'dart:async';

import 'package:codingtalk_firebase_crud/model/databrg.dart';
import 'package:codingtalk_firebase_crud/ui/detail_page.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<Barang> _brgList = [];

  final FirebaseDatabase _database = FirebaseDatabase.instance;
  DatabaseReference? _brgRef;

  final _namaBrgController = TextEditingController();
  final _priceController = TextEditingController();
  final _stockController = TextEditingController();
  final _descController = TextEditingController();

  StreamSubscription<Event>? _onBrgAddedSubscription;
  StreamSubscription<Event>? _onBrgChangedSubscription;

  @override
  void initState() {                                 //menjalankan proses saat terjadi perubahan data
    _brgRef = _database.reference().child('brg');
    _onBrgAddedSubscription = _brgRef?.onChildAdded.listen(_onNewBrg);
    _onBrgChangedSubscription = _brgRef?.onChildChanged.listen(_onChangedBrg);

    super.initState();
  }

  @override
  void dispose() {                         //menghentikan semua proses ketika sudah tidak di page tsb agar tidak
    _onBrgAddedSubscription?.cancel();     //memakan banyak srouce pada device
    _onBrgChangedSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Data Storage App'),
      ),
      body: Container(
        child: _showBrgList(),  //memisahkan data dalam bentuk fungsi widget, yg nantinya akan menampilkan data
      ),                        //tsb
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _showDialogBrgForm(); //penjelasan sama dengan di atas
        },
        child: Icon(Icons.add),
      ),
    );
  }

  Widget? _showBrgList() {             //fungsi widget data menampilkan list barang
    if (_brgList.length > 0) {
      return ListView.builder(
        itemCount: _brgList.length,
        itemBuilder: (context, index) {
          Barang barang = _brgList[index];
          return Dismissible(          //ini berfungsi untuk menghapus data dengan slide ke kiri ataupun kanan
            key: Key(barang.key!),
            background: Container(
              color: Colors.red,
            ),
            onDismissed: (direction) async {
              if (_deleteBrg != null) {
                _deleteBrg(barang.key!, index);
              }
            },
            child: Card(
              child: ListTile(
                onTap: () {
                  //detail
                  Navigator.push(context, MaterialPageRoute(builder: (context)=>DetailPage(barang, _brgRef)));
                },
                title: Text(
                  barang.namaBrg ?? '-',
                  style: TextStyle(fontSize: 20, color: Colors.green),
                ),
                subtitle: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      'Rp ${barang.price}',
                      style: TextStyle(fontSize: 12, color: Colors.black),
                    ),
                    Text(
                      "Stock : ${barang.stock}",
                      style: TextStyle(fontSize: 12, color: Colors.black),
                    )
                  ],
                ),
                trailing: IconButton(
                  icon: (barang.favorite ?? false)
                      ? Icon(
                          Icons.star,
                          color: Colors.yellowAccent,
                          size: 20,
                        )
                      : Icon(
                          Icons.star,
                          color: Colors.grey,
                          size: 20,
                        ),
                  onPressed: () {
                    _updateFavorite(barang);
                  },
                ),
              ),
            ),
          );
        },
      );
    } else {
      return Center(
        child: Text('No Data Storage'),
      );
    }
  }

  void _showDialogBrgForm() {             //fungsi widget pop up input data
    _namaBrgController.clear();
    _priceController.clear();
    _stockController.clear();
    _descController.clear();
    showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            scrollable: true,
            content: Column(
              children: [
                TextField(
                  controller: _namaBrgController,
                  autofocus: true,
                  decoration: InputDecoration(labelText: 'Nama Barang'),
                ),
                TextField(
                  controller: _priceController,
                  decoration: InputDecoration(labelText: 'Price'),
                ),
                TextField(
                  controller: _stockController,
                  decoration: InputDecoration(labelText: 'Stock'),
                ),
                TextField(
                  controller: _descController,
                  decoration: InputDecoration(labelText: 'Deskripsi'),
                ),
              ],
            ),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('Cancel'),
              ),
              TextButton(
                onPressed: () {  //data akan di simpan ke database saat menekan button save
                  _addBrg(_namaBrgController.text, _priceController.text, _stockController.text, _descController.text);
                  Navigator.pop(context);
                },

                child: Text('Save'),
              ),
            ],
          );
        });
  }

  //listener
  void _onNewBrg(Event event) {
    setState(() {
      _brgList.add(Barang.fromSnapshot(event.snapshot));
    });
  }

  void _onChangedBrg(Event event) {
    var oldEntry = _brgList.singleWhere((barang) {
      return barang.key == event.snapshot.key;
    });
    setState(() {
      _brgList[_brgList.indexOf(oldEntry)] =
          Barang.fromSnapshot(event.snapshot);
    });
  }

  //CRUD
  Future<void> _deleteBrg(String key, int index) async {
    await _brgRef?.child(key).remove();
    setState(() {
      _brgList.removeAt(index);
    });
  }

  Future<void> _updateFavorite(Barang barang) async {
    barang.favorite = !barang.favorite!;
    await _brgRef?.child(barang.key!).set(barang.toJson());
  }

  Future<void> _addBrg(String namaBrg, String price,
      String stock, String desc) async {
    if (namaBrg.length > 0){
      Barang barang = Barang(
          namaBrg: namaBrg,
          price: price,
          stock: stock,
          desc:  desc,
          favorite: false
      );

      await _brgRef?.push().set(barang.toJson());
    }

  }
}

Selanjutnya file detail_page.dart yang berguna menampilkan data barang secara detail, di sini kita hanya cukup mamanggil datanya saja untuk di tampilkan, selain itu juga ada pop up untuk mengedit data tersebut.

import 'package:codingtalk_firebase_crud/model/databrg.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';

class DetailPage extends StatefulWidget{
  final Barang? barang;
  DatabaseReference? _brgRef;

  DetailPage(this.barang, this._brgRef);


  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  TextEditingController? namaBrgEdit;
  TextEditingController? priceEdit;
  TextEditingController? stockEdit;
  TextEditingController? descEdit;

  @override
  void initState() {         
    namaBrgEdit = TextEditingController(text: widget.barang!.namaBrg);
    priceEdit = TextEditingController(text: widget.barang!.price);
    stockEdit = TextEditingController(text: widget.barang!.stock);
    descEdit = TextEditingController(text: widget.barang!.desc);
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(''),
      ),
      body: ListView(  //tampilan detail barang
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Card(
              child: Column(
                children: [
                  Text('${widget.barang!.namaBrg}', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
                  SizedBox(height: 8,),
                  Text('${widget.barang!.price}', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
                  Divider(),
                  Column(
                    children: [
                      Text('Deskripsi produk', style: TextStyle(fontSize: 10),),
                      Text('${widget.barang!.desc}', style: TextStyle(fontSize: 10),)
                    ],
                  )
                ],
              ),
            ),
          )
        ],
      ),
      floatingActionButton: FloatingActionButton(  //menampilkan data yang akan di edit
        onPressed: (){
          _showDialogEdit();  //dibuatkan fungsi widget nya
        },
        child: Icon(Icons.edit),
      ),
    );
  }

  void _showDialogEdit() {  //fungsi widget untuk pop up update data
    showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            scrollable: true,
            content: Column(
              children: [
                TextField(
                  controller: namaBrgEdit,
                  autofocus: true,
                  decoration: InputDecoration(labelText: 'Nama Barang'),
                ),
                TextField(
                  controller: priceEdit,
                  decoration: InputDecoration(labelText: 'Price'),
                ),
                TextField(
                  controller: stockEdit,
                  decoration: InputDecoration(labelText: 'Stock'),
                ),
                TextField(
                  controller: descEdit,
                  decoration: InputDecoration(labelText: 'Deskripsi'),
                ),
              ],
            ),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('Cancel'),
              ),
              TextButton(           //data akan terupdate saat tombol save di tekan
                onPressed: () {
                  _updateBrg(namaBrgEdit!.text, priceEdit!.text, stockEdit!.text, descEdit!.text, widget.barang?.favorite ?? false);
                },
                child: Text('Save'),
              ),
            ],
          );
        });
  }

  Future<void> _updateBrg (namaBrgEdit, priceEdit, stockEdit, descEdit, favorite) async {
    Barang barang = Barang(
      namaBrg: namaBrgEdit,
      price: priceEdit,
      stock: stockEdit,
      desc: descEdit,
      favorite: favorite
    );
    await widget._brgRef?.child(widget.barang!.key!).set(barang.toJson());
  }
}

Jika sudah kita dapat melakukan running project, berikut demo aplikasinya serta tampilan realtime database pada firebase

Klik di sini untuk kembali ke Part 1