Building a Flutter Firebase Firestore CRUD App
In this tutorial, we will walk you through the process of creating a Flutter application that performs CRUD (Create, Read, Update, Delete) operations on a list of items using Firebase Firestore. Firestore is a cloud-based NoSQL database provided by Firebase, and Flutter is a powerful open-source framework for building cross-platform mobile apps. By combining these technologies, you can create a real-time and cloud-synced list management app.
Prerequisites
Before we start, ensure that you have the following prerequisites in place:
Adding Dependencies
First, we need to add the necessary dependencies to our Flutter project. Open your project's pubspec.yaml file and add the following dependencies:
dependencies:
flutter:
sdk: flutter
firebase_core: ^latest_version
cloud_firestore: ^latest_version
Replace latest_version with the actual latest versions of the firebase_core and cloud_firestore packages available on the Flutter packages website (https://pub.dev/).
After adding the dependencies, run the following command in your terminal to fetch and install them:
flutter pub get
- Go to the Firebase Console (https://console.firebase.google.com/).
- Create a new project if you haven't already.
- Add your Flutter app to the project by clicking on the "Add App" button. Follow the on-screen instructions to register your app with Firebase.
- Download the google-services.json file and place it in the android/app directory of your Flutter project for Android, or the ios/Runner directory for iOS.
- Initialize Firebase in your Flutter app by opening your main.dart file and adding the following code in the main() function:
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_example/firebase_options.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firestore Example',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final FirebaseFirestore firestore = FirebaseFirestore.instance;
final TextEditingController textEditingController = TextEditingController();
@override
void initState() {
super.initState();
}
void _addItem() async {
if (textEditingController.text.isNotEmpty) {
await firestore
.collection('items')
.add({'name': textEditingController.text});
//_fetchData();
textEditingController.clear();
}
}
Future<void> deleteItem(String documentId) async {
try {
await FirebaseFirestore.instance
.collection('items')
.doc(documentId)
.delete();
print('Item deleted successfully');
} catch (e) {
print('Error deleting item: $e');
}
}
Future<void> _showDeleteConfirmationDialog(String documentId) async {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Delete Item'),
content: Text('Are you sure you want to delete this item?'),
actions: <Widget>[
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Delete'),
onPressed: () {
deleteItem(documentId);
Navigator.of(context).pop();
},
),
],
);
},
);
}
Future<void> _showEditItemDialog(String documentId, String itemName) async {
textEditingController.text = itemName;
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Edit Item'),
content: TextField(
controller: textEditingController,
decoration: InputDecoration(labelText: 'Edit Item'),
),
actions: <Widget>[
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Save'),
onPressed: () async {
String updatedName = textEditingController.text;
await FirebaseFirestore.instance
.collection('items')
.doc(documentId)
.update({'name': updatedName});
textEditingController.clear();
Navigator.of(context).pop();
},
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Firestore Example'),
),
body: Column(
children: <Widget>[
TextField(
controller: textEditingController,
decoration: InputDecoration(labelText: 'Enter Item'),
),
ElevatedButton(
onPressed: _addItem,
child: Text('Add Item'),
),
Expanded(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('items')
.snapshots(),
builder:
(context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot documentSnapshot =
streamSnapshot.data!.docs[index];
// return InkWell(
// onTap: () {
// // deleteItem(documentSnapshot.id);
//
// _showDeleteConfirmationDialog(documentSnapshot.id);
// },
// child: Text(streamSnapshot.data!.docs[index]['name']));
return ListTile(
title: Text(streamSnapshot.data!.docs[index]['name']),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
setState(() {
_showEditItemDialog(documentSnapshot.id,
documentSnapshot['name']);
textEditingController.clear();
});
},
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
_showDeleteConfirmationDialog(
documentSnapshot.id);
},
),
],
),
);
},
);
})),
],
),
);
}
}
Conclusion
In this tutorial, we've created a Flutter app that seamlessly integrates Firebase Firestore, enabling users to perform CRUD operations on a list of items. We've provided code explanations and highlighted essential functionalities for adding, editing, and deleting items.
You can find the complete code in the provided snippet above. Feel free to use it as a reference or customize it to meet your project's specific requirements. This app serves as a solid foundation for building more advanced Firestore-based applications.
Happy coding!
Comments
Post a Comment