๐bikin aplikasi daftar pelajar kekinian pakai flutter web + simpan data di cache browser,gak perlu backend!
๐bikin aplikasi daftar pelajar kekinian pakai flutter web + simpan data di cache browser,gak perlu backend!
Halo Sobat Koding! ๐✨
Kali ini gue bakal share proyek keren buat kalian yang pengen belajar Flutter Web dengan cara yang asik dan praktis. Jadi, gue bikin aplikasi daftar pelajar yang bisa lo Tambah, Edit, dan Hapus data dengan mudah banget. Tapi bedanya, data yang lo masukin gak bakal ilang meskipun lo tutup browser atau refresh halaman, soalnya kita simpen semua datanya di cache browser Chrome alias pakai localStorage! ๐๐ฅ
Buat lo yang masih newbie di Flutter atau pengen bikin project sederhana buat tugas sekolah/kampus, ini aplikasi pas banget. Gak perlu ribet setting backend server, gak perlu database, karena data langsung nyimpen di browser kalian sendiri. Jadi lebih hemat waktu dan lebih gampang buat di-deploy. Lo juga bisa langsung coba jalanin di platform online kayak Zapp.run tanpa perlu install apapun.
Apa aja sih yang lo dapetin dari aplikasi ini?
CRUD lengkap — lo bisa tambah pelajar baru, edit data pelajar yang udah ada, dan hapus juga kalau gak perlu.
Penyimpanan lokal — data tersimpan otomatis di cache Chrome, aman dan gak hilang walaupun browser ditutup.
Tampilan simpel tapi kece — UI modern dan bersih dengan warna yang eye-catching, biar makin semangat ngekode!
Cocok buat belajar Flutter Web — kode gampang dipahami, rapi, dan langsung jalan tanpa konfigurasi ribet.
Mudah di-custom — lo bisa tambahin fitur sendiri, misalnya search, filter, atau export data.
Cara pakainya?
Copy paste kode lengkap yang gue sediain di bawah ke project Flutter Web lo, atau langsung tempelin di Zapp.run.
Jalankan aplikasinya, dan cobain tambah data pelajar baru.
Edit atau hapus data kalau perlu.
Refresh browser, dan lihat data lo tetep utuh!
Bisa lo share ke temen, atau jadi portofolio keren.
Code nya
import 'dart:convert';
import 'dart:html' as html;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class Pelajar {
final String id;
String nama;
String kelas;
Pelajar({required this.id, required this.nama, required this.kelas});
Map<String, dynamic> toJson() => {'id': id, 'nama': nama, 'kelas': kelas};
factory Pelajar.fromJson(Map<String, dynamic> json) {
return Pelajar(id: json['id'], nama: json['nama'], kelas: json['kelas']);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CRUD Pelajar',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: PelajarPage(),
);
}
}
class PelajarPage extends StatefulWidget {
@override
_PelajarPageState createState() => _PelajarPageState();
}
class _PelajarPageState extends State<PelajarPage> {
final List<Pelajar> _pelajars = [];
@override
void initState() {
super.initState();
_loadData();
}
void _simpanKeStorage() {
final jsonList = _pelajars.map((e) => e.toJson()).toList();
html.window.localStorage['pelajars'] = jsonEncode(jsonList);
}
void _loadData() {
final jsonStr = html.window.localStorage['pelajars'];
if (jsonStr != null) {
final decoded = jsonDecode(jsonStr);
_pelajars.clear();
_pelajars.addAll((decoded as List).map((e) => Pelajar.fromJson(e)));
setState(() {});
}
}
void _tambahPelajar(String nama, String kelas) {
setState(() {
final id = DateTime.now().millisecondsSinceEpoch.toString();
_pelajars.add(Pelajar(id: id, nama: nama, kelas: kelas));
_simpanKeStorage();
});
}
void _editPelajar(String id, String nama, String kelas) {
final index = _pelajars.indexWhere((e) => e.id == id);
if (index != -1) {
setState(() {
_pelajars[index].nama = nama;
_pelajars[index].kelas = kelas;
_simpanKeStorage();
});
}
}
void _hapusPelajar(String id) {
setState(() {
_pelajars.removeWhere((e) => e.id == id);
_simpanKeStorage();
});
}
void _showForm({Pelajar? pelajar}) {
final namaController = TextEditingController(text: pelajar?.nama ?? '');
final kelasController = TextEditingController(text: pelajar?.kelas ?? '');
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) => Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, MediaQuery.of(context).viewInsets.bottom + 20),
child: Wrap(
children: [
Text(
pelajar == null ? 'Tambah Pelajar' : 'Edit Pelajar',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 12),
TextField(
controller: namaController,
decoration: InputDecoration(labelText: 'Nama', border: OutlineInputBorder()),
),
SizedBox(height: 12),
TextField(
controller: kelasController,
decoration: InputDecoration(labelText: 'Kelas', border: OutlineInputBorder()),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
final nama = namaController.text.trim();
final kelas = kelasController.text.trim();
if (nama.isEmpty || kelas.isEmpty) return;
if (pelajar == null) {
_tambahPelajar(nama, kelas);
} else {
_editPelajar(pelajar.id, nama, kelas);
}
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.teal,
foregroundColor: Colors.white,
minimumSize: Size(double.infinity, 50),
),
child: Text(pelajar == null ? 'Tambah' : 'Simpan'),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Daftar Pelajar'),
centerTitle: true,
backgroundColor: Color.fromARGB(255, 27, 0, 150),
foregroundColor: Colors.white,
),
body: _pelajars.isEmpty
? Center(child: Text('Belum ada data pelajar'))
: ListView.builder(
itemCount: _pelajars.length,
padding: EdgeInsets.all(16),
itemBuilder: (context, index) {
final pelajar = _pelajars[index];
return Card(
margin: EdgeInsets.only(bottom: 12),
child: ListTile(
title: Text(pelajar.nama),
subtitle: Text('Kelas: ${pelajar.kelas}'),
trailing: PopupMenuButton<String>(
onSelected: (value) {
if (value == 'edit') {
_showForm(pelajar: pelajar);
} else if (value == 'hapus') {
_hapusPelajar(pelajar.id);
}
},
itemBuilder: (context) => [
PopupMenuItem(value: 'edit', child: Text('Edit')),
PopupMenuItem(value: 'hapus', child: Text('Hapus')),
],
),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _showForm(),
backgroundColor: Color.fromARGB(255, 22, 0, 150),
child: Icon(Icons.add),
),
);
}
}
hasil:https://zk1806o3k190.zapp.page/
lupa like, share, dan komen ya! Gue bakal seneng banget kalau ada feedback atau ide fitur baru yang pengen lo lihat di project berikutnya.
Happy coding dan semangat terus belajar Flutter Web! ๐✨

Komentar
Posting Komentar