Flutter - How can I print all my data (fields) from firebase documents? - firebase

I would like to show all the fields of a document in firebase, but I'm having different troubles.
My intention is to show the info like a chat. I tried with a ListView.builder inside a StreamBuilder.
This is my Firestore document:
I managed to get the horizontal information using doc.data().toString but what I am trying to do is to get the whole information as a ListTile so when I add new messages they are automatically added to the ListView.builder.
This is my current code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({Key? key}) : super(key: key);
#override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final textController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: StreamBuilder(
stream:
FirebaseFirestore.instance.collection("messages").snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot doc = snapshot.data!.docs[index];
return ListTile(
title: Text(doc.data().toString()),
);
},
);
}),
),
);
}
}
And this is what I get with my current code: DeviceImage
P.S. I can get the data manually if I use this but it's not what I want:
return ListTile(
title: Text(doc['sender']),
);

Try to use an Object like below.
class Message {
final String sender;
final String text;
const Message({
required this.sender,
required this.text,
});
Map<String, dynamic> toMap() {
return {
'sender': sender,
'text': text,
};
}
factory Message.fromMap(Map<String, dynamic> map) {
return Message(
sender: map['sender'] as String,
text: map['text'] as String,
);
}
}
class ChatScreen extends StatelessWidget {
const ChatScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder<List<Message>>(
stream: FirebaseFirestore.instance
.collection("messages")
.snapshots()
.map((query) =>
query.docs.map((map) => Message.fromMap(map.data())).toList()),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final msgList = snapshot.data!;
return ListView.builder(
itemCount: msgList.length,
itemBuilder: (context, index) {
final message = msgList[index];
return ListTile(
title: Text(message.text),
leading: Text(message.sender),
);
},
);
});
}
}

Try with this.
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("messages")
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
return ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: snapshot.hasData ? snapshot.data.docs.length : 0,
itemBuilder: (context, index) {
final data = MessageModel.fromSnapshot(snapshot.data.docs[index]);
return ListTile(
title: Text(data.text),
subtitle: Text(data.sender),
);
},
);
},
);
MessageModel
class MessageModel {
MessageModel({
this.sender,
this.text,
});
String sender;
String text;
String toRawJson() => json.encode(toJson());
factory MessageModel.fromSnapshot(DocumentSnapshot snapshot) {
final model =
MessageModel.fromJson(snapshot.data() as Map<String, dynamic>);
return model;
}
factory MessageModel.fromJson(Map<String, dynamic> json) => MessageModel(
sender: json["sender"] == null ? null : json["sender"],
text: json["text"] == null ? null : json["text"],
);
Map<String, dynamic> toJson() => {
"sender": sender == null ? null : sender,
"text": text == null ? null : text,
};
}

Related

How to display Image in App with flutter and firebase using URL as String in Firestore

we have no clue how to display an image in a flutter app via an URL from Firebase Firestore.
Here is a Picture of our database with three fields one of which is for a picture. In that we placed the URL of the Image we want to display.
We know how to display Text from that database, as you can see in our code. Now we want to simply display an image from the database.
Currently we use Image() with NetworkImage() where we placed a var "imageURL". That works fine.
How can we tell the var "ImageURL" to use the URL out of the database.
Here is our code:
class DataFavorites extends StatefulWidget {
const DataFavorites({Key? key}) : super(key: key);
#override
_DataFavoritesState createState() => _DataFavoritesState();
}
class _DataFavoritesState extends State<DataFavorites> {
var imageURL = 'https://previews.123rf.com/images/gumbao/gumbao1509/gumbao150900016/44987080-kiefer-firest-auf-la-marina-an-der-k%C3%BCste-des-mittelmeers-costa-blanca-spanien.jpg';
final Stream<QuerySnapshot> _data = FirebaseFirestore.instance.collection('favoriten').snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
body:
StreamBuilder<QuerySnapshot>(
stream: _data,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String,
dynamic>;
return ListTile(
title: Text(data['Name'],style: Theme.of(context).textTheme.headline1,
),
subtitle: Image(
image: NetworkImage(imageURL),
width: 300,
height: 300,
),
);
}).toList(),
);
},
),
);
}
}
Thanks in advance!
You should give the parameter of image url to the NetworkImage widget
You code should look like this
class DataFavorites extends StatefulWidget {
const DataFavorites({Key? key}) : super(key: key);
#override
_DataFavoritesState createState() => _DataFavoritesState();
}
class _DataFavoritesState extends State<DataFavorites> {
var imageURL = 'https://previews.123rf.com/images/gumbao/gumbao1509/gumbao150900016/44987080-kiefer-firest-auf-la-marina-an-der-k%C3%BCste-des-mittelmeers-costa-blanca-spanien.jpg';
final Stream<QuerySnapshot> _data = FirebaseFirestore.instance.collection('favoriten').snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
body:
StreamBuilder<QuerySnapshot>(
stream: _data,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String,
dynamic>;
return ListTile(
title: Text(data['Name'],style: Theme.of(context).textTheme.headline1,
),
subtitle: Image(
image: NetworkImage(data['Bild']), // ----------- the line that should change
width: 300,
height: 300,
),
);
}).toList(),
);
},
),
);
}
}

How to use StreamBuilder to listen for a document change in Firestore

My goal is to refactor the code below to use a StreamBuilder. It has been suggested that I could improve my code even further by using a StreamBuilder but after a few days of trying I honestly can't figure out what to do or where to begin.
I want the user interface and the Firestore database to react to user taps on a switch tile. The boolean value in Firestore should toggle when the user clicks the switch and the switch tile user interface should update accordingly.
The code below works just fine but it doesn't use a StreamBuilder.
Thanks in advance for any help.
class InterestsFitnessTile extends StatefulWidget {
const InterestsFitnessTile({
Key? key,
}) : super(key: key);
#override
State<InterestsFitnessTile> createState() => _InterestsFitnessTileState();
}
class _InterestsFitnessTileState extends State<InterestsFitnessTile> {
bool isFitnessActive = true;
final String? currentSignedInUserID = Auth().currentUser?.uid;
Future<void> _updateFitnessSetting() async {
await Auth()
.userInterestsSettingsReference
.doc(currentSignedInUserID)
.update({
AuthString.fitness: isFitnessActive,
});
setState(() {
isFitnessActive = !isFitnessActive;
});
}
#override
Widget build(BuildContext context) {
return SwitchListTileSliver(
icon: Provider.of<InterestsPageProvider>(context).isFitnessTurnedOff
? Icons.thumb_down
: Icons.thumb_up,
onChanged: (value) {
final provider = Provider.of<InterestsPageProvider>(
context,
listen: false,
);
provider.updateFitnessSettings(isOn: value);
_updateFitnessSetting();
},
subTitle: Provider.of<InterestsPageProvider>(context).isFitnessTurnedOff
? const Text(
SettingsPageString.fitnessOff,
)
: const Text(
SettingsPageString.fitnessOn,
),
title: SettingsPageString.fitness,
value: Provider.of<InterestsPageProvider>(context).isFitnessTurnedOff,
);
}
}
class InterestsPageProvider extends ChangeNotifier {
bool _currentFitness = false;
bool get isFitnessTurnedOff => _currentFitness == true;
void updateFitnessSettings({required bool isOn}) {
_currentFitness = !_currentFitness;
notifyListeners();
}
}
Here are two examples in which I have used Streambuilder:
Example 1:
class Messages extends StatelessWidget {
const Messages({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final currentUser = FirebaseAuth.instance.currentUser!.uid;
return StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance
.collection("chat")
.orderBy("createdAt", descending: true)
.snapshots(),
builder: (ctx, snapShot) {
if (snapShot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
final chatDocs = snapShot.data!.docs;
return ListView.builder(
reverse: true,
itemBuilder: (ctx, i) => MessageBubble(
chatDocs[i]['text'],
chatDocs[i]['userName'],
chatDocs[i]['userId'] == currentUser,
chatDocs[i]['userImg'],
),
itemCount: chatDocs.length,
);
}
},
);}}
Example 2:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => CarsProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (ctx, snapShot) =>
snapShot.hasData ? const HomePage() : const UserAuth(),
),
routes: {
HomePage.routeName: (_) => const HomePage(),
SearchPage.routeName: (_) => const SearchPage(),
SearchedItemDetail.routeName: (_) => const SearchedItemDetail(),
ForgotPassword.routeName: (_) => const ForgotPassword(),
AddItem.routeName: (_) => const AddItem(),
},
),
);
}
}

How to get document id in firestore flutter using QuerySnapshot

I am trying to get data (In real-time) from my database using QuerySnapshot.
and I need to update my data as well. This is my method and I don't know how to get my documentID in this method.
class LoadData extends StatefulWidget {
const LoadData({Key? key}) : super(key: key);
#override
_LoadDataState createState() => _LoadDataState();
}
class _LoadDataState extends State<LoadData> {
//Read Data in realTime Snapshot
final Stream<QuerySnapshot> _cupCakeStream = FirebaseFirestore.instance
.collection('cupcake')
.snapshots(includeMetadataChanges: true);
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _cupCakeStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
shrinkWrap: true,
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
print(data); //**Print collection only..I need to get documentID with each collection**
return ListTile(
title: Text(data['cupcake_name']),
subtitle: Text(data['description']),
);
}).toList(),
);
},
);
}
}
document is a DocumentSnapshot and has an id property.
So, the following should do the trick:
return ListView(
shrinkWrap: true,
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
print(data);
print(document.id); // <= Should print the doc id
return ListTile(
title: Text(data['cupcake_name']),
subtitle: Text(data['description']),
);
}).toList(),
);

Deleting Firestore Data in Flutter List View

I have a regular List View that fetches some data from Firestore, here is the code for it:
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection('orders').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(
child:
CircularProgressIndicator(),
);
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.docs[index];
return Text(ds['name']);
Now if I wanted to create a delete button somewhere in it, I would do something like this:
FirebaseFirestore.instance.collection('orders').doc('ID SHOULD BE HERE').delete();
The issue I have is how do I find the document ID of the list tile on here in order to delete it automatically from the database? ID SHOULD BE HERE in the code should be some command to find the id of it like in the screenshot below:
DocumentSnapshot contains a property called id which will return the document's given ID for this snapshot. Therefore you can do the following:
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.docs[index];
print(ds.id);
return Text(ds['name']);
And then to delete it according to the id, do the following:
FirebaseFirestore.instance.collection('orders').doc(ds.id).delete();
By saving the reference id from doc in local model and using the reference id on your required set of operation
I have provide the realtime example of removing the data.
class Employee {
Employee(this.employeeID, this.employeeName, this.branch, this.designation, this.location,
this.salary,
{this.reference});
double employeeID;
String employeeName;
String designation;
String branch;
String location;
double salary;
DocumentReference reference;
factory Employee.fromSnapshot(DocumentSnapshot snapshot) {
Employee newEmployee = Employee.fromJson(snapshot.data());
newEmployee.reference = snapshot.reference;
return newEmployee;
}
factory Employee.fromJson(Map<String, dynamic> json) =>
_employeeFromJson(json);
Map<String, dynamic> toJson() => _employeeToJson(this);
#override
String toString() => 'employeeName ${employeeName}';
}
Employee _employeeFromJson(Map<String, dynamic> data) {
return Employee(
data['employeeID'],
data['employeeName'],
data['branch'],
data['designation'],
data['location'],
data['salary'],
);
}
Map<String, dynamic> _employeeToJson(Employee instance) {
return {
'employeeID' : instance.employeeID,
'employeeName': instance.employeeName,
'branch': instance.branch,
'designation': instance.designation,
'location': instance.location,
'salary': instance.salary,
};
}
Repository
class EmployeeRepository{
List<Employee> employees = [];
final CollectionReference collection =
FirebaseFirestore.instance.collection('employees');
Stream<QuerySnapshot> getStream() {
return collection.snapshots();
}
Future<DocumentReference> add(Employee employee) {
var documentReference = collection.add(employee.toJson());
return documentReference;
}
update(Employee employee) async {
collection.doc(employee.reference.id).update(employee.toJson());
}
delete(Employee employee) async {
collection.doc(employee.reference.id).delete();
}
fromSnapShot(DocumentSnapshot snapshot) => Employee.fromSnapshot(snapshot);
Future<void> buildData(AsyncSnapshot snapshot) async {
if (snapshot.data.documents.length == 0) {
employees = [];
}
employees = await snapshot.data.documents.map<Employee>((doc) {
return Employee.fromSnapshot(doc);
}).toList(growable: false);
}
}
Listview builder
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Employees List'),
),
body: Column(children: [
StreamBuilder<QuerySnapshot>(
stream: employeeRepository.getStream(),
builder: (context, snapShot) {
if (!snapShot.hasData ||
snapShot.hasError ||
snapShot.connectionState == ConnectionState.waiting) {
return Container(
child: Center(child: CircularProgressIndicator()),
);
}
employeeRepository.buildData(snapShot);
return ListView.builder(
itemBuilder: (context, index) {
final employee = employeeRepository.employees[index];
return ListTile(
title: Text(employee.employeeName),
onLongPress: () {
showDialog<AlertDialog>(
context: context,
builder: (context) {
return AlertDialog(
actions: [
FlatButton(
onPressed: () {},
child: Text('Edit')),
FlatButton(
onPressed: () {
setState(() {
employeeRepository
.delete(employee);
Navigator.pop(context);
});
},
child: Text('Delete')),
],
content: Text(employee.employeeName),
);
});
},
);
},
);
}),
]),
);
}
CRUD Operation in firestore

Get data from Cloud firestore and displays them into widget

Below you can see a code where I want to display data that I have collected from a registration form in Flutter.
the registration form push the data to a collection called " user " then some other documents data are pushed as:
name - email etc...
As you can see by XXXX I want that the data I retrieve from cloud firestore be shown into the widget:
Below the code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class WelcomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.pink,
body: MainWelcome(),
);
}
}
class MainWelcome extends StatefulWidget {
#override
_MainWelcomeState createState() => _MainWelcomeState();
}
class _MainWelcomeState extends State<MainWelcome> {
final databaseReference = Firestore.instance;
Future<QuerySnapshot> getData() async {
return await Firestore.instance.collection("user").getDocuments();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getData(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
snapshot.data.documents.forEach((element) {
Center(
child: Text(
'Benvenuta ${element.data["name"]}',
style: TextStyle(fontSize: 20, color: Colors.white),
),
);
});
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return Center(child: CircularProgressIndicator());
},
);
}
}
You need to use a FutureBuilder widget to display the data in the widget tree:
Create a method that returns the data:
Future<QuerySnapshot> getData() async {
return await Firestore.instance
.collection("user")
.where("email", isEqualTo: "email_here")
.getDocuments();
}
Then inside the build() method do the following:
FutureBuilder(
future: getData(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
title:
Text(snapshot.data.documents[index].data["name"]),
);
});
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
),

Resources