Forum Replies Created
-
AuthorPosts
-
notes.dart coach..
import ‘dart:io’;
import ‘package:flutter/cupertino.dart’;
import ‘package:notes/api/note_api.dart’;
import ‘package:notes/database/database_helper.dart’;
import ‘package:notes/models/note.dart’;class Notes with ChangeNotifier {
List<Note> _notes = [
Note(
id: ‘N1’,
title: ‘Catatan Materi Flutter’,
note:
‘Flutter merupakan Software Development Kit (SDK) yang bisa membantu developer dalam membuat aplikasi mobile cross platform. Kelas ini akan mempelajari pengembangan aplikasi mobile yang dapat dijalankan baik di IOS maupun di Android’,
updatedAt: DateTime.parse(‘2021-05-19 20:33:33’),
createdAt: DateTime.parse(‘2021-05-19 20:33:33’),
),
Note(
id: ‘N2’,
title: ‘Target Pembelajaran Flutter’,
note:
‘Peserta dapat mengembangkan aplikasi mobile (IOS dan Android) menggunakan flutter,\nPeserta memahami konsep pengembangan aplikasi menggunakan flutter,\nPeserta dapat menjalankan aplikasi mobile di IOS dan Android ataupun Emulator,\nPeserta memahami bahasa pemrograman Dart,\nPeserta dapat mendevelop aplikasi mobile menggunakan flutter dan dart dari dasar secara berurutan.’,
updatedAt: DateTime.parse(‘2021-05-20 20:53:33’),
createdAt: DateTime.parse(‘2021-05-20 20:53:33’),
),
Note(
id: ‘N3’,
title: ‘Belajar Flutter di ITBOX’,
note: ‘Jangan lupa belajar flutter dengan video interactive di ITBOX.’,
updatedAt: DateTime.parse(‘2021-05-20 21:22:33’),
createdAt: DateTime.parse(‘2021-05-20 21:22:33’),
),
Note(
id: ‘N4’,
title: ‘Resep nasi goreng’,
note:
‘Nasi putih 1 piring\nBawang putih 2 siung, cincang halus\nKecap manis atau kecap asin sesuai selera\nSaus sambal sesuai selera\nSaus tiram sesuai selera\nGaram secukupnya\nKaldu bubuk rasa ayam atau sapi sesuai selera\nDaun bawang 1 batang, cincang halus\nTelur ayam 1 butir\nSosis ayam 1 buah, iris tipis\nMargarin atau minyak goreng 3 sdm.’,
updatedAt: DateTime.parse(‘2021-05-20 21:51:33’),
createdAt: DateTime.parse(‘2021-05-20 21:51:33’),
),
];Future<void> getAndSetNotes() async {
// tambahkan fungsi try & catch untuk mengatasi error
try {
_notes = await NoteApi().getAllNote();
// fungsi untuk gunakan getAllNote ke provider
await DatabaseHelper().insertAllNote(_notes);
notifyListeners();
} on SocketException {
// tambahkan fungsi agar saat internet tidak tersambung yang ditampilkan adalah data dari database
_notes = await DatabaseHelper().getAllNote();
notifyListeners();
} catch (e) {
return Future.error(e);
}
}List<Note> get notes {
// mengurutkan note ( yang di pin ditampilkan lebih dahulu)
List<Note> tempListNote = _notes.where((note) => note.isPinned).toList();
tempListNote.addAll(_notes.where((note) => !note.isPinned).toList());
return tempListNote;
}// menambahkan toggleIsPinned untuk merubah isPinned yang true ke false dan sebaliknya
Future<void> toggleIsPinned(String? id) async {
// menampung atau mencari note dengan id yang sama
int index = notes.indexWhere((note) => note.id == id);
try {
// melakukan validasi
if (index >= 0) {
_notes[index].isPinned = !_notes[index].isPinned;
// ganti tanggal update pada server
_notes[index] = _notes[index].copyWith(updatedAt: DateTime.now());
// tambahkan notifier untuk memberi tau widget yang listen ke provider bahwa data sudah berubah
notifyListeners();
// panggil fungsi toggleIsPinned pada API sebelum notifyListeners
await NoteApi().toggleIsPinned(
id, _notes[index].isPinned, _notes[index].updatedAt!);
// setelah update toggleIspinned ke API maka akan update toggleIspinned di databaseHelper
await DatabaseHelper().toogleIspinned(
id,
_notes[index].isPinned,
_notes[index].updatedAt!,
);
}
} catch (e) {
_notes[index].isPinned = !_notes[index].isPinned;
notifyListeners();
return Future.error(e);
}
}// 1. fungsi addNote untuk menambahkan note ke provider
Future<void> addNote(Note note) async {
try {
// 2. panggil fungsi postNote dan tambahkan await, future dan async
// 3. tampung return id dari API dengan membuat String id:
String? id = await NoteApi().postNote(note);
// 4. sebelum tambahkan notes ke dalam _notes buat note.copyWith(id: id saat kita post)
note = note.copyWith(id: id);
// setelah add note ke API maka akan add note di databaseHelper
await DatabaseHelper().insertNote(note);
_notes.add(note);
notifyListeners();
} catch (e) {
return Future.error(e);
}
}Note getNote(String? id) {
return _notes.firstWhere((note) => note.id == id);
}// Fungsi untuk update
Future<void> updateNote(Note newNote) async {
try {
// sebelum updateNote ke dalam listnote panggil dulu fungsi NoteApi
await NoteApi().updateNote(newNote);
// setelah update note ke API maka akan update note di databaseHelper
await DatabaseHelper().updateNote(newNote);
int index = _notes.indexWhere((note) => note.id == newNote.id);
_notes[index] = newNote;
notifyListeners();
} catch (e) {
return Future.error(e);
}
}// fungsi untuk delete note ketika di swap kiri atau kanan
Future<void> deleteNote(String? id) async {
// tambahkan fungsi agar pada saat error apa yang sudah di remove dibalikkan lagi
int index = _notes.indexWhere((note) => note.id == id);
Note tempNote = _notes[index];
try {
_notes.removeAt(index);
// _notes.removeWhere((note) => note.id == id);
notifyListeners();
// panggil fungsi delete pada note.api
await NoteApi().deleteNote(id);
// setelah delete note ke API maka akan delete note di databaseHelper
await DatabaseHelper().deleteNote(id);
} catch (e) {
_notes.insert(index, tempNote);
notifyListeners();
return Future.error(e);
}
}
}Saya coba matikan internet dan hot reload, note yang tersimpan sebelumnya bisa muncul, namun jika internet di hidupkan dan di hot reload lagi kembali terjadi error pada emulator = Exeption = Error terjadi kesalahan..
Mohon petunjuknya coach..
ini kode add_or_detail_screen coach:
import ‘dart:ffi’;
import ‘package:flutter/material.dart’;
import ‘package:intl/intl.dart’;
import ‘package:notes/models/note.dart’;
import ‘package:notes/providers/notes.dart’;
import ‘package:provider/provider.dart’;class AddOrDetailScreen extends StatefulWidget {
static const routeName = ‘/addOrDetailScreen’;
@override
State<AddOrDetailScreen> createState() => _AddOrDetailScreenState();
}class _AddOrDetailScreenState extends State<AddOrDetailScreen> {
Note _note = Note(
id: ”,
title: ”,
note: ”,
// updatedAt: null,
// createdAt: null,
);bool _init = true;
// tambah parameter untuk penanda sedang loading atau tidak saat simpan note
bool _isLoading = false;final _formKey = GlobalKey<FormState>();
void submitNote() async {
// tambahkan validasi (if) karena migrasi ke null
if (_formKey.currentState != null) {
_formKey.currentState!.save();
}
// set isLoading jadi true
setState(() {
_isLoading = true;
});
try {
final now = DateTime.now();
_note = _note.copyWith(updatedAt: now, createdAt: now);
final notesProvider = Provider.of<Notes>(context, listen: false);
if (_note.id == null) {
await notesProvider.addNote(_note);
} else {
await notesProvider.updateNote(_note);
}
} catch (e) {
await showDialog(
context: context,
builder: (builder) {
return AlertDialog(
title: Text(‘Error’),
content: Text(e.toString()),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(‘Tutup’),
)
],
);
},
);
}
// notesProvider.addNote(_note);
Navigator.of(context).pop();
}@override
void didChangeDependencies() {
if (_init) {
String? id = ModalRoute.of(context)!.settings.arguments as String?;
// tambahkan fungsi if untuk validasi penambahan note baru
//jika id tidak sama dengan null baru cari note dari provider,
//jika null berarti note baru dan tidak perlu cari data atau id dalam provider
if (id != null) {
_note = Provider.of<Notes>(context).getNote(id);
}
_init = false;
}
super.didChangeDependencies();
}// fungsi untuk merubah format waktu di detail note
String _convertDate(DateTime dateTime) {
int diff = DateTime.now().difference(dateTime).inDays;
if (diff > 0) return DateFormat(‘dd-MM-yyyy’).format(dateTime);return DateFormat(‘hh-mm’).format(dateTime);
}@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
TextButton(
onPressed: submitNote,
// tambahkan fungsi isLoading
child: _isLoading
? CircularProgressIndicator()
: Text(
‘Simpan’,
style: TextStyle(color: Colors.white),
),
)
],
),
body: Stack(
children: [
Container(
height: double.infinity,
padding: EdgeInsets.all(12),
// wrap dengan SingleChildScrollView agar bisa di scroll
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
// tambahkan initialValue agar saat note ditekan memunculkan judul
initialValue: _note.title,
decoration: InputDecoration(
hintText: ‘Judul’, border: InputBorder.none),
onSaved: (value) {
_note = _note.copyWith(title: value);
},
),
TextFormField(
// tambahkan initialValue agar saat note ditekan memunculkan isi note
initialValue: _note.note,
decoration: InputDecoration(
hintText: ‘Tulis Catatan Disini…’,
border: InputBorder.none),
onSaved: (value) {
_note = _note.copyWith(note: value);
},
// tambahkan maxLines untuk menampilkan note tulisan ke bawah
maxLines: null,
),
],
)),
),
),
// 1. Untuk menampilkan kapan note terakhir diubah
// 2. wrap dengan Positioned agar update waktu pindah ke bawah
// 3. tambahkan fungsi if karena ada penambahan note baru sedangkan note.updatedAt masih null
// 4. jika note.updated tidak null maka baru tampilkan kapan terakhir diubah note nya
if (_note.updatedAt != null)
Positioned(
bottom: 10,
right: 10,
child: Text(‘Terakhir diubah ${_convertDate(_note.updatedAt!)}’),
),
],
),
);
}
}Sudah bisa jalan cocah.. Saya coba ganti di pubspec.yaml path nya dari 1.8.2 ke 1.8.1..tetimakasih sebelum nya coach
Code database_helper.dart
import ‘package:notes/models/note.dart’;
import ‘package:path/path.dart’;
import ‘package:sqflite/sqflite.dart’;class DatabaseHelper {
// tambahkan variable static const untuk menghindari typo dan memudahkan merubah nama table
static const TABLE_NOTES = ‘notes’;
static const TABLE_NOTES_ID = ‘id’;
static const TABLE_NOTES_NOTE = ‘note’;
static const TABLE_NOTES_TITLE = ‘title’;
static const TABLE_NOTES_ISPINNED = ‘isPinned’;
static const TABLE_NOTES_UPDATEDAT = ‘updated_at’;
static const TABLE_NOTES_CREATEDAT = ‘created_at’;// buat fungsi untuk open database
static Future<Database> init() async {
final dbPath = await getDatabasesPath();
return openDatabase(join(dbPath, ‘notes.db’), version: 1,
onCreate: (newDb, version) {
newDb.execute(”’
CREATE TABLE $TABLE_NOTES (
$TABLE_NOTES_ID TEXT PRIMARY KEY,
$TABLE_NOTES_TITLE TEXT,
$TABLE_NOTES_NOTE TEXT,
$TABLE_NOTES_ISPINNED INTEGER,
$TABLE_NOTES_UPDATEDAT TEXT,
$TABLE_NOTES_CREATEDAT TEXT
)
”’);
});
}// buat fungsi untuk mendapatkan atau select note nya
Future<List<Note>> getAllNote() async {
final db = await DatabaseHelper.init();
final result = await db.query(‘notes’);List<Note> listNote = [];
result.forEach((data) {
listNote.add(Note.fromDb(data));
});return listNote;
}// buat fungsi untuk insert semua note
Future<void> insertAllNote(List<Note> listNote) async {
final db = await DatabaseHelper.init();
// fungsi Batch untuk insert banyak data
Batch batch = db.batch();listNote.forEach((note) {
batch.insert(
‘notes’,
note.toDb(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
});await batch.commit();
}// fungsi untuk update data pada database helper
Future<void> updateNote(Note note) async {
final db = await DatabaseHelper.init();
await db.update(TABLE_NOTES, note.toDb(),
where: ‘$TABLE_NOTES_ID = ?’, whereArgs: [note.id]);
}// fungsi untuk update toogleIspinned pada database helper
Future<void> toogleIspinned(
String id, bool isPinned, DateTime updatedAt) async {
final db = await DatabaseHelper.init();
await db.update(
TABLE_NOTES,
{
TABLE_NOTES_ISPINNED: isPinned ? 1 : 0,
TABLE_NOTES_UPDATEDAT: updatedAt.toIso8601String(),
},
where: ‘$TABLE_NOTES_ID = ?’,
whereArgs: [id],
);
}// fungsi untuk update deleteNote pada database helper
Future<void> deleteNote(String id) async {
final db = await DatabaseHelper.init();
await db.delete(TABLE_NOTES, where: ‘$TABLE_NOTES_ID = ?’, whereArgs: [id]);
}
}July 1, 2022 at 8:04 PM in reply to: Saat simpan dan update note, note tercipta ganda(jadi dua) #51428iya sudah bisa coach terimaksih..
June 30, 2022 at 3:29 PM in reply to: Saat simpan dan update note, note tercipta ganda(jadi dua) #51261detail kode nya ada disini coach : https://github.com/Vram-AH/aplikasi-notes-flutter/tree/master/lib
June 30, 2022 at 3:18 PM in reply to: Saat simpan dan update note, note tercipta ganda(jadi dua) #51258CODE notes.dart
import ‘package:flutter/cupertino.dart’;
import ‘package:notes/api/note_api.dart’;
import ‘package:notes/models/note.dart’;class Notes with ChangeNotifier {
List<Note> _notes = [
Note(
id: ‘N1’,
title: ‘Catatan Materi Flutter’,
note:
‘Flutter merupakan Software Development Kit (SDK) yang bisa membantu developer dalam membuat aplikasi mobile cross platform. Kelas ini akan mempelajari pengembangan aplikasi mobile yang dapat dijalankan baik di IOS maupun di Android’,
updatedAt: DateTime.parse(‘2021-05-19 20:33:33’),
createdAt: DateTime.parse(‘2021-05-19 20:33:33’),
),
Note(
id: ‘N2’,
title: ‘Target Pembelajaran Flutter’,
note:
‘Peserta dapat mengembangkan aplikasi mobile (IOS dan Android) menggunakan flutter,\nPeserta memahami konsep pengembangan aplikasi menggunakan flutter,\nPeserta dapat menjalankan aplikasi mobile di IOS dan Android ataupun Emulator,\nPeserta memahami bahasa pemrograman Dart,\nPeserta dapat mendevelop aplikasi mobile menggunakan flutter dan dart dari dasar secara berurutan.’,
updatedAt: DateTime.parse(‘2021-05-20 20:53:33’),
createdAt: DateTime.parse(‘2021-05-20 20:53:33’),
),
Note(
id: ‘N3’,
title: ‘Belajar Flutter di ITBOX’,
note: ‘Jangan lupa belajar flutter dengan video interactive di ITBOX.’,
updatedAt: DateTime.parse(‘2021-05-20 21:22:33’),
createdAt: DateTime.parse(‘2021-05-20 21:22:33’),
),
Note(
id: ‘N4’,
title: ‘Resep nasi goreng’,
note:
‘Nasi putih 1 piring\nBawang putih 2 siung, cincang halus\nKecap manis atau kecap asin sesuai selera\nSaus sambal sesuai selera\nSaus tiram sesuai selera\nGaram secukupnya\nKaldu bubuk rasa ayam atau sapi sesuai selera\nDaun bawang 1 batang, cincang halus\nTelur ayam 1 butir\nSosis ayam 1 buah, iris tipis\nMargarin atau minyak goreng 3 sdm.’,
updatedAt: DateTime.parse(‘2021-05-20 21:51:33’),
createdAt: DateTime.parse(‘2021-05-20 21:51:33’),
),
];Future<void> getAndSetNotes() async {
_notes = await NoteApi().getAllNote();
notifyListeners();
}List<Note> get notes {
// mengurutkan note ( yang di pin ditampilkan lebih dahulu)
List<Note> tempListNote = _notes.where((note) => note.isPinned).toList();
tempListNote.addAll(_notes.where((note) => !note.isPinned).toList());
return tempListNote;
}// menambahkan toogleIspinned untuk merubah isPinned yang true ke false dan sebaliknya
void toogleIspinned(String id) {
// menampung atau mencari note dengan id yang sama
int index = notes.indexWhere((note) => note.id == id);
// melakukan validasi
if (index >= 0) {
_notes[index].isPinned = !_notes[index].isPinned;
// tambahkan notifier untuk memberi tau widget yang listen ke provider bahwa data sudah berubah
notifyListeners();
}
}// 1. fungsi addNote untuk menambahkan note ke provider
Future<void> addNote(Note note) async {
// 2. panggil fungsi postNote dan tambahkan await, future dan async
// 3. tampung return id dari API dengan membuat String id:
String id = await NoteApi().postNote(note);
// 4. sebelum tambahkan notes ke dalam _notes buat note.copyWith(id: id saat kita post)
note = note.copyWith(id: id);
_notes.add(note);
notifyListeners();
}Note getNote(String id) {
return _notes.firstWhere((note) => note.id == id);
}// Fungsi untuk update
Future<void> updateNote(Note newNote) async {
// sebelum updateNote ke dalam listnote panggil dulu fungsi NoteApi
await NoteApi().updateNote(newNote);
int index = _notes.indexWhere((note) => note.id == newNote.id);
_notes[index] = newNote;
notifyListeners();
}// fungsi untuk delete note ketika di swap kiri atau kanan
void deleteNote(String id) {
_notes.removeWhere((note) => note.id == id);
notifyListeners();
}
}June 30, 2022 at 3:17 PM in reply to: Saat simpan dan update note, note tercipta ganda(jadi dua) #51257KODE add_or_detail_screen
import ‘dart:ffi’;
import ‘package:flutter/material.dart’;
import ‘package:intl/intl.dart’;
import ‘package:notes/models/note.dart’;
import ‘package:notes/providers/notes.dart’;
import ‘package:provider/provider.dart’;class AddOrDetailScreen extends StatefulWidget {
static const routeName = ‘/addOrDetailScreen’;
@override
State<AddOrDetailScreen> createState() => _AddOrDetailScreenState();
}class _AddOrDetailScreenState extends State<AddOrDetailScreen> {
Note _note = Note(
id: null,
title: ”,
note: ”,
updatedAt: null,
createdAt: null,
);bool init = true;
final _formKey = GlobalKey<FormState>();
void submitNote() {
_formKey.currentState.save();
final now = DateTime.now();
_note = _note.copyWith(updatedAt: now, createdAt: now);
final notesProvider = Provider.of<Notes>(context, listen: false);
if (_note.id == null) {
notesProvider.addNote(_note);
} else {
notesProvider.updateNote(_note);
}
notesProvider.addNote(_note);
Navigator.of(context).pop();
}@override
void didChangeDependencies() {
if (init) {
String id = ModalRoute.of(context).settings.arguments as String;
// tambahkan fungsi if untuk validasi penambahan note baru
//jika id tidak sama dengan null baru cari note dari provider,
//jika null berarti note baru dan tidak perlu cari data atau id dalam provider
if (id != null) {
_note = Provider.of<Notes>(context).getNote(id);
}
init = false;
}
super.didChangeDependencies();
}// fungsi untuk merubah format waktu di detail note
String _convertDate(DateTime dateTime) {
int diff = DateTime.now().difference(dateTime).inDays;
if (diff > 0) return DateFormat(‘dd-MM-yyyy’).format(dateTime);return DateFormat(‘hh-mm’).format(dateTime);
}@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
TextButton(
onPressed: submitNote,
child: Text(‘Simpan’),
)
],
),
body: Stack(
children: [
Container(
height: double.infinity,
padding: EdgeInsets.all(12),
// wrap dengan SingleChildScrollView agar bisa di scroll
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
// tambahkan initialValue agar saat note ditekan memunculkan judul
initialValue: _note.title,
decoration: InputDecoration(
hintText: ‘Judul’, border: InputBorder.none),
onSaved: (value) {
_note = _note.copyWith(title: value);
},
),
TextFormField(
// tambahkan initialValue agar saat note ditekan memunculkan isi note
initialValue: _note.note,
decoration: InputDecoration(
hintText: ‘Tulis Catatan Disini…’,
border: InputBorder.none),
onSaved: (value) {
_note = _note.copyWith(note: value);
},
// tambahkan maxLines untuk menampilkan note tulisan ke bawah
maxLines: null,
),
],
)),
),
),
// 1. Untuk menampilkan kapan note terakhir diubah
// 2. wrap dengan Positioned agar update waktu pindah ke bawah
// 3. tambahkan fungsi if karena ada penambahan note baru sedangkan note.updatedAt masih null
// 4. jika note.updated tidak null maka baru tampilkan kapan terakhir diubah note nya
if (_note.updatedAt != null)
Positioned(
bottom: 10,
right: 10,
child: Text(‘Terakhir diubah ${_convertDate(_note.updatedAt)}’),
),
],
),
);
}
}var pertanyaan = [
{
‘pertanyaan’: ‘Tempat apa yang akan anda kunjungi?’,
‘jawban’: [‘Pegunungan’, ‘Pantai’, ‘Mall’, ‘Hutan’],
},
{
‘pertanyaan’: ‘Apa warna kesukaan anda?’,
‘jawban’: [‘Merah’, ‘Biru’, ‘Hijau’, ‘Hitam’],
},
{
‘pertanyaan’: ‘Apa hobi anda?’,
‘jawban’: [‘Sepak Bola’, ‘Basket’, ‘Berenang’, ‘Ngoding’],
},
];Sudah bisa coach ada typo di ‘jawaban’
-
AuthorPosts