Simple Firestore Todo +-----------------------------+ | Add Todo: [__________] [+] | +-----------------------------+ | Todos: | | 1. Buy groceries [Edit][X]| | 2. Walk the dog [Edit][X]| | | +-----------------------------+
Cloud Firestore CRUD in Flutter - Mini App: Build & Ship
import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; class SimpleFirestoreTodo extends StatefulWidget { @override State<SimpleFirestoreTodo> createState() => _SimpleFirestoreTodoState(); } class _SimpleFirestoreTodoState extends State<SimpleFirestoreTodo> { final TextEditingController _controller = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Simple Firestore Todo')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Row( children: [ Expanded( child: TextField( controller: _controller, decoration: InputDecoration(hintText: 'Add Todo'), ), ), IconButton( icon: Icon(Icons.add), onPressed: () { // TODO: Add new todo to Firestore }, ), ], ), Expanded( child: StreamBuilder<QuerySnapshot>( stream: FirebaseFirestore.instance.collection('todos').snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) return CircularProgressIndicator(); final docs = snapshot.data!.docs; return ListView.builder( itemCount: docs.length, itemBuilder: (context, index) { final doc = docs[index]; final todoText = doc['text']; return ListTile( title: Text(todoText), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon(Icons.edit), onPressed: () { // TODO: Edit todo text }, ), IconButton( icon: Icon(Icons.delete), onPressed: () { // TODO: Delete todo }, ), ], ), ); }, ); }, ), ), ], ), ), ); } }
import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; class SimpleFirestoreTodo extends StatefulWidget { @override State<SimpleFirestoreTodo> createState() => _SimpleFirestoreTodoState(); } class _SimpleFirestoreTodoState extends State<SimpleFirestoreTodo> { final TextEditingController _controller = TextEditingController(); void _addTodo() async { final text = _controller.text.trim(); if (text.isEmpty) return; await FirebaseFirestore.instance.collection('todos').add({'text': text}); _controller.clear(); } void _deleteTodo(String id) async { await FirebaseFirestore.instance.collection('todos').doc(id).delete(); } void _editTodoDialog(String id, String currentText) { final editController = TextEditingController(text: currentText); showDialog( context: context, builder: (context) => AlertDialog( title: Text('Edit Todo'), content: TextField( controller: editController, autofocus: true, decoration: InputDecoration(hintText: 'Todo text'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('Cancel'), ), TextButton( onPressed: () async { final newText = editController.text.trim(); if (newText.isNotEmpty) { await FirebaseFirestore.instance.collection('todos').doc(id).update({'text': newText}); } Navigator.pop(context); }, child: Text('Save'), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Simple Firestore Todo')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Row( children: [ Expanded( child: TextField( controller: _controller, decoration: InputDecoration(hintText: 'Add Todo'), onSubmitted: (_) => _addTodo(), ), ), IconButton( icon: Icon(Icons.add), onPressed: _addTodo, tooltip: 'Add todo', ), ], ), Expanded( child: StreamBuilder<QuerySnapshot>( stream: FirebaseFirestore.instance.collection('todos').snapshots(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: CircularProgressIndicator()); } if (!snapshot.hasData || snapshot.data!.docs.isEmpty) { return Center(child: Text('No todos yet')); } final docs = snapshot.data!.docs; return ListView.builder( itemCount: docs.length, itemBuilder: (context, index) { final doc = docs[index]; final todoText = doc['text'] ?? ''; return ListTile( title: Text(todoText), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon(Icons.edit), tooltip: 'Edit todo', onPressed: () => _editTodoDialog(doc.id, todoText), ), IconButton( icon: Icon(Icons.delete), tooltip: 'Delete todo', onPressed: () => _deleteTodo(doc.id), ), ], ), ); }, ); }, ), ), ], ), ), ); } }
This app uses Cloud Firestore to store todo items in a collection called 'todos'.
The _addTodo method adds a new document with the todo text. It clears the input after adding.
The _deleteTodo method deletes a document by its ID.
The _editTodoDialog shows a dialog with a TextField to update the todo text. On save, it updates the Firestore document.
The UI listens to live updates from Firestore using StreamBuilder and shows the list of todos. Each todo has Edit and Delete buttons.
This approach keeps the UI in sync with the database automatically.
Simple Firestore Todo +-----------------------------+ | Add Todo: [Buy milk ] [+] | +-----------------------------+ | Todos: | | 1. Buy groceries [Edit][X]| | 2. Walk the dog [Edit][X]| | 3. Buy milk [Edit][X]| +-----------------------------+
Practice
What does CRUD stand for in Cloud Firestore operations?
Solution
Step 1: Understand CRUD acronym meaning
CRUD is a common term in databases meaning the four basic operations on data.Step 2: Match each letter to the correct operation
C = Create, R = Read, U = Update, D = Delete are the standard meanings.Final Answer:
Create, Read, Update, Delete -> Option CQuick Check:
CRUD = Create, Read, Update, Delete [OK]
- Confusing CRUD letters with unrelated words
- Mixing up 'Remove' with 'Delete'
- Thinking CRUD includes 'Download'
Which Flutter code snippet correctly adds a new document to a Firestore collection named users?
FirebaseFirestore.instance.collection('users').____({'name': 'Alice'});Solution
Step 1: Identify method to add new document
Theaddmethod creates a new document with given data in the collection.Step 2: Confirm other methods' purposes
updatemodifies existing documents,deleteremoves documents,getreads data.Final Answer:
add -> Option BQuick Check:
Adding new document uses add() [OK]
- Using update() to add new documents
- Confusing get() with add()
- Trying to delete() when adding data
What will be the output of this Flutter Firestore code snippet?
var doc = await FirebaseFirestore.instance.collection('tasks').doc('task1').get();
print(doc.exists);Assuming the document task1 exists in the tasks collection.
Solution
Step 1: Understand doc.get() behavior
Theget()method fetches the document snapshot from Firestore.Step 2: Check the
If the document exists,existspropertydoc.existsreturns true; otherwise false.Final Answer:
true -> Option AQuick Check:
Document exists property = true [OK]
- Assuming doc.exists returns document data
- Expecting false even if document exists
- Not awaiting the get() call
Identify the error in this Flutter Firestore update code:
FirebaseFirestore.instance.collection('users').doc('user1').update({'age': 30});Assuming the document user1 does not exist.
Solution
Step 1: Understand update() behavior on missing document
Theupdate()method requires the document to exist; otherwise, it throws an error.Step 2: Confirm no syntax errors
The syntax is correct, so error is due to missing document.Final Answer:
Throws an error because document does not exist -> Option DQuick Check:
update() fails if document missing [OK]
- Thinking update() creates new documents
- Confusing update() with set()
- Ignoring async/await for update()
You want to delete a Firestore document only if it exists to avoid errors. Which Flutter code snippet correctly does this?
var docRef = FirebaseFirestore.instance.collection('orders').doc('order1');
// What code to safely delete?Solution
Step 1: Check document existence before deleting
Useget()to fetch the document snapshot and checkexists.Step 2: Call delete() only if document exists
This avoids errors from deleting non-existing documents.Final Answer:
docRef.get().then((doc) { if (doc.exists) docRef.delete(); }); -> Option AQuick Check:
Check exists before delete to avoid errors [OK]
- Calling delete() without checking existence
- Using update() to delete documents
- Setting document to null instead of deleting
Ready to prove it?
Pass the test and this pattern moves unknown
