Tutorial Flutter dengan Laravel Rest API #5: Edit dan Update di Flutter dengan Rest API


Tutorial Flutter dengan Laravel Rest API #5: Edit dan Update di Flutter dengan Rest API

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.


Membangun Website dan Aplikasi Android Desa Dengan Laravel, React.js dan React Native

Membangun Aplikasi dan Website News Dengan Laravel, React.js dan Android


Faisal Mahadi
Mobile Apps Developer | Android Enthusiast | Keep Learning | Android Dev Serta Owner Hariankoding.com

Suka dengan tulisan di SantriKoding? Kamu bisa memberikan dukungan dengan berdonasi atau bagikan konten ini di sosial media. Terima kasih atas dukungan Anda!

KEBIJAKAN KOMENTAR

Saat memberikan komenatar silahkan memberikan informasi lengkap tentang error, seperti: screenshot, link kode, dll. Baca aturan komentar kami