Halo teman-teman sebelumnya kita sudah tahu cara untuk insert data post, pada tutorial kali ini kita akan edit dan update data post.
Langkah 1 – Memberi Action Pada Icon Edit
Untuk langkah pertama kita memberi action navigati dengan mengirim parameter pada class AddEditPostScreen
, sebelumnya kalian buat constructur pada class AddEditPostScreen
, sehingga menjadi berikut:
class AddEditPostScreen extends StatefulWidget {
final Post? post;
const AddEditPostScreen({
super.key,
this.post,
});
@override
State<AddEditPostScreen> createState() => _AddEditPostScreenState();
}
lalu tambahkan navigation untuk mengarah ke AddEditPostScreen pada file home.dart
, tambhakan kode pada comment // TODO action to edit post , menjadi berikut:
Positioned(top: 2,
right: 2,
child: IconButton(
onPressed: () async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddEditPostScreen(post: post),
),
);
if (result == true) {
_currentPage = 1;
_posts.clear();
_hasMore = true;
_loadPosts();
}
},
icon: const Icon(Icons.edit_rounded),
),
),
Langkah 2 – Menangkap data dan menampilkan
Langkah selanjutkan kita akan menangkap dan menampilkan data, sehingga menjadi berikut keseluruhan kode
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter_pemula/api/repository.dart';
import 'package:flutter_pemula/model/post.dart';
class AddEditPostScreen extends StatefulWidget {
final Post? post;
const AddEditPostScreen({
super.key,
this.post,
});
@override
State<AddEditPostScreen> createState() => _AddEditPostScreenState();
}
class _AddEditPostScreenState extends State<AddEditPostScreen> {
final _formKey = GlobalKey<FormState>();
final _titleController = TextEditingController();
final _contentController = TextEditingController();
final _titleFocus = FocusNode();
final _contentFocus = FocusNode();
File? _image;
final picker = ImagePicker();
final Repository apiService = Repository();
Future getImage() async {
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No Image Selected')),
);
}
});
}
@override
void dispose() {
_titleController.dispose();
_contentController.dispose();
_titleFocus.dispose();
_contentFocus.dispose();
super.dispose();
}
@override
void initState() {
if (widget.post != null) {
_titleController.text = widget.post!.title;
_contentController.text = widget.post!.content;
}
super.initState();
}
Future<void> _submitData() async {
if (_formKey.currentState!.validate()) {
bool success = false;
if (widget.post != null) {
success = await apiService.updatePost(
_image,
_titleController.text,
_contentController.text,
widget.post!.id,
);
} else if (_image != null) {
success = await apiService.insertPost(
_image,
_titleController.text,
_contentController.text,
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please Insert Image'),
backgroundColor: Colors.red,
),
);
}
if (!mounted) return;
if (success) {
Navigator.pop(context, true);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Failed to Create Post')),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.post == null ? 'Add New Post' : 'Edit Post'),
),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Center(
child: _image == null
? const Text('No Image Selected')
: Image.file(
_image!,
height: 200,
width: 200,
),
),
const SizedBox(
height: 8.0,
),
TextButton(
onPressed: getImage,
child: const Text('Selected Image'),
),
const SizedBox(
height: 8.0,
),
TextFormField(
controller: _titleController,
focusNode: _titleFocus,
textInputAction: TextInputAction.next,
onFieldSubmitted: (value) {},
decoration: const InputDecoration(
labelText: 'Title',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please Insert Title';
} else {
return null;
}
},
),
const SizedBox(
height: 16.0,
),
TextFormField(
controller: _contentController,
focusNode: _contentFocus,
textInputAction: TextInputAction.done,
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: const InputDecoration(
labelText: 'Content',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please Insert Some Text';
} else {
return null;
}
},
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: () => _submitData(),
child: Text(widget.post == null ? 'Submit' : 'Update'),
),
),
],
),
),
),
),
);
}
}
Perubahan dan penambahan kode diatas adalah berikut:
@override
void initState() {
if (widget.post != null) {
_titleController.text = widget.post!.title;
_contentController.text = widget.post!.content;
}
super.initState();
}
kode diatas yaitu fungsi ketika widget pertama kali dibuat, maka akan melakukan cek jika ada data tidak bernilai null atau kosong pada variable widget.post
, maka akan di masukkan pada controller.
Future<void> _submitData() async {
if (_formKey.currentState!.validate()) {
bool success = false;
if (widget.post != null) {
success = await apiService.updatePost(
_image,
_titleController.text,
_contentController.text,
widget.post!.id,
);
} else if (_image != null) {
success = await apiService.insertPost(
_image,
_titleController.text,
_contentController.text,
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please Insert Image'),
backgroundColor: Colors.red,
),
);
}
if (!mounted) return;
if (success) {
Navigator.pop(context, true);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Failed to Create Post')),
);
}
}
}
Lalu pada perubahan fungsi submitData()
, yaitu mengecek terlebih dahulu jika data variable widget.post
tidak bernilai null atau kosong maka kita akan meng-update data ke server dengan fungsi apiService.updatePost
.
Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.post == null ? 'Add New Post' : 'Edit Post'),
),
Pada widget Scafflod pada title kita buat di namis jika ada data dari widget.post maka akan menampilkan Edit Post jika tidak ada data maka akan menampilkan Add New Post.
FilledButton(onPressed: () => _submitData(),
child: Text(widget.post == null ? 'Submit' : 'Update'),),
Lalu kita juga buat text dinami pada button Sumbit sehinga ketika ada data pada widget.post maka text nya akan bertuliskan Update jika tidak akan bertuliskan submit.
Coba Sekarang kalian jalan dan lihat apa yang berubah.
Kesimpulan
OK teman-teman pada artikel kali ini kita belajar cara edit dan update data serta membuat tampilan yang awalnya untuk insert data sekarang bisa digunakan juga untuk edit dan update data.
Untuk tutorial selanjutnya kita akan belajar bagaiman cara hapus data.
Tutorial Flutter dengan Laravel Rest API #6: Delete Data di Flutter dari Rest API
Membangun Website dan Aplikasi Android Desa Dengan Laravel, React.js dan React Native
Membangun Aplikasi dan Website News Dengan Laravel, React.js dan Android