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()); | |
}), | |
), | |
); | |
} | |
} |
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'))); | |
} | |
} |
If you have any question, feel free to ask here π
Join the Next Dev Discord Server!
Top comments (0)