DEV Community

Cover image for Flutter: πŸ”΄ How to Update and Delete Data in Supabase || Part β€” 4
Next Dev
Next Dev

Posted on

1

Flutter: πŸ”΄ How to Update and Delete Data in Supabase || Part β€” 4

Hey there πŸ‘‹, in this blog post, you will learn how to **update **and **delete **the data in supabase using flutter packages (supabase_flutter).

If you want to know how to use supabase in flutter
Flutter Supabase

If you understand Hindi πŸ‘‡


Now, let’s begin with update and delete functions

Please continue this blog if you are familiar with this one πŸ‘‡
Flutter: πŸ”΄ How to Create and Read data || Future Builder || Part β€” 3

import 'package:flutter_supabase_yt_1/models/models.dart'; // this is being used to import the todo.dart from models file.
import 'package:supabase_flutter/supabase_flutter.dart';
class SupabaseDataManager {
// create function which takes one argument of Todo
Future<PostgrestResponse<dynamic>> createData(Todo todo) async {
PostgrestResponse<dynamic> res = await Supabase.instance.client
.from('todos')
// here πŸ‘‡ you need to make todo.toMap() because we need to make Todo model to map --> eg Todo(title: 'This is first todo') -> {'title': 'This is first todo'}
.insert(todo.toMap())
.execute();
return res;
}
// read function
Future<PostgrestResponse<dynamic>> readData() async {
PostgrestResponse<dynamic> res = await Supabase.instance.client
.from('todos')
.select('id, title')
.execute();
return res;
}
// update function
Future<PostgrestResponse<dynamic>> updateTodo(Todo todo) async {
// upsert or update
PostgrestResponse<dynamic> res = await Supabase.instance.client
.from('todos')
.update({'title': todo.title})
.eq('id', todo.id)
.execute();
return res;
}
// delete function
Future<PostgrestResponse<dynamic>> deleteTodo(int todoId) async {
PostgrestResponse<dynamic> res = await Supabase.instance.client
.from('todos')
.delete()
.eq('id', todoId)
.execute();
return res;
}
}

This is the read screen.

In the part -3 , I just showed how to load the data. But in this part, you will learn how to delete and update the data.

Delete Button β†’ You can see Delete button in the **trailing **of the list tile.

Update Button β†’ You can see this in **onTap **of the list tile.

import 'package:flutter/material.dart';
import 'package:flutter_supabase_yt_1/models/models.dart';
import 'package:flutter_supabase_yt_1/screens/create_screen.dart';
import 'package:flutter_supabase_yt_1/screens/home_screen.dart';
import 'package:flutter_supabase_yt_1/screens/screens.dart';
import 'package:flutter_supabase_yt_1/utils/utils.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
class ReadScreen extends StatelessWidget {
const ReadScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
List<Todo>? _todos;
SupabaseDataManager supabaseDataManager = SupabaseDataManager();
Future<List<Todo>> readData() async {
PostgrestResponse<dynamic> res = await supabaseDataManager.readData();
if (res.error != null) {
throw Exception(res.error!.message);
}
// Todo --> [Todo(id: 1, title: 'This'),Todo(id: 2, title: 'fafdaf')]
// Map --> [{'id' : 1, 'title': 'This'},{'id' : 2, 'title': 'adfafaf'}]
return (res.data as List<dynamic>).map((e) => Todo.fromMap(e)).toList();
}
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (route) => const CreateScreen()));
},
icon: const Icon(Icons.create))
],
),
body: FutureBuilder(
future: readData(),
builder: ((context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text(snapshot.error.toString()));
} else if (snapshot.hasData) {
return ListView.builder(
itemCount: (snapshot.data! as List<Todo>).length,
itemBuilder: ((BuildContext context, int index) {
Todo todo = (snapshot.data! as List<Todo>)[index];
return ListTile(
leading: Text(todo.id.toString()),
title: Text(todo.title),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (route) => EditScreen(todo: todo)));
},
trailing: IconButton(
onPressed: () async {
var res = await supabaseDataManager.deleteTodo(todo.id!);
if (res.error != null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Error: ${res.error!.message}')));
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Deleted ${todo.title}')));
},
icon: Icon(Icons.delete),
),
);
}),
);
}
// until the data has been loaded, we will see this progess indicator.
return const Center(child: CircularProgressIndicator());
}),
),
);
}
}
view raw read_screen.dart hosted with ❀ by GitHub

Now comes, the edit screen
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:flutter_supabase_yt_1/models/models.dart';
import 'package:flutter_supabase_yt_1/utils/utils.dart';
class EditScreen extends StatefulWidget {
const EditScreen({
Key? key,
required this.todo,
}) : super(key: key);
// this is the arguments for the edit screen.
// Whenever we route to editscreen, we need to pass the todo.
// This is done because then only we can fetch the title and id of the todo.
// You can achieve this type of quality by using state mangagement also.
final Todo todo;
@override
State<EditScreen> createState() => _EditScreenState();
}
class _EditScreenState extends State<EditScreen> {
TextEditingController todoController = TextEditingController();
@override
void initState() {
// we are changing the value of todoController so that the title which user
// has set can be showed in the controller as default.
todoController.text = widget.todo.title;
super.initState();
}
@override
void dispose() {
todoController.dispose();
super.dispose();
}
// instance
SupabaseDataManager supabaseDataManager = SupabaseDataManager();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Create')),
body: Padding(
padding: const EdgeInsets.all(20),
child: Form(
child: Column(
children: [
TextFormField(
// controller
controller: todoController,
decoration: const InputDecoration(hintText: 'Todo'),
),
ElevatedButton(onPressed: _updateData, child: const Text('Update'))
],
)),
),
);
}
Future _updateData() async {
// we are changing the todoController title value so that we don't have to write the todo again.
// we are just using the todo from the arguments πŸ‘†, but we are changing the title to todoController text value.
Todo todo = widget.todo.copyWith(title: todoController.text);
PostgrestResponse<dynamic> res = await supabaseDataManager.updateTodo(todo);
if (res.error != null) {
// ignore: use_build_context_synchronously
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(res.error!.message)));
}
// ignore: use_build_context_synchronously
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Updated')));
}
}
view raw edit_screen.dart hosted with ❀ by GitHub

If you have any question, feel free to ask here πŸ‘‡
Join the Next Dev Discord Server!

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

Sentry growth stunted Image

If you are wasting time trying to track down the cause of a crash, it’s time for a better solution. Get your crash rates to zero (or close to zero as possible) with less time and effort.

Try Sentry for more visibility into crashes, better workflow tools, and customizable alerts and reporting.

Switch Tools

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay