Retrieve Map Data in Firebase to Flutter - firebase

I have this data structure
Database Structure
I need to call all the item in the FavDestination collection and here is my code in Flutter
child: StreamBuilder(
stream: Firestore.instance.collection('FavDestination').snapshots(),
builder: (context, snapshot){
if(!snapshot.hasData) return Text('Loading Data... Please Wait');
return
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.documents.length, //snapshot.data.document.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot destination = snapshot.data.documents[index];
//DocumentSnapshot destination = snapshot.data.document[index];
return GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => DestinationScreen(
destination: destination,
),
),
),
It retrieves the data successfully, and if the user taps on the document, it will go to Destination Screen and I need to retrieve all the data in activities, here is my code in the Destination Screen
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(top: 10.0, bottom: 15.0),
itemCount: widget.destination['activities'].length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot activity = widget.destination['activities'][index];
return Stack(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 120.0,
child: Text(
activity['name'],
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
),
and here is the Error I got
Error Message
any idea how to solve it? Thank you

It seems that your activities field is nested map. On first level you have field Bali1 which is map as well. And it the code activity is trying to get name on first level.
I suppose you should work more on destination object structure. You can print it out to analyze and try to map object like Map<dynamic, dynamic> and Bali1 as well.
I don't have playground to do it fast, but I found similar approach here:
How do I get specific values from a datasnapshot in flutter?
I hope it will help!

Related

How to create Foreign key in firebase for chat app

I create chat app applicattion have many conversation which i can have conversation, my problem depend on receive messages by another account.
most work correctly but when i loggin to another user i receive the same messages as in the previous one user which didn't conduct a conversation.
i suppose i need foregin key
Column(children:
[
StreamBuilder(
//currentLoggedUserId - user which is logged right now
stream:FirebaseFirestore.instance.collection('users').doc(currentLoggedUserId).snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot)
{
return Center(child:
ListView.builder(
shrinkWrap:true,
itemCount: snapshot.data['messages'].length,
itemBuilder: (BuildContext context, int index){
return ChatBubble(
clipper: ChatBubbleClipper1(type: BubbleType.sendBubble),
alignment: Alignment.topRight,
margin: EdgeInsets.only(top: 20),
backGroundColor: Colors.blue,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.7,
),
child: Text(
snapshot.data['messages'][index],
style: TextStyle(color: Colors.white),
),
),
);
},),
);
}),
StreamBuilder(
//writer is DocumentId account which i have conversation
stream:FirebaseFirestore.instance.collection('users').doc(writer).snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot)
{
return Center(child:
ListView.builder(
shrinkWrap:true,
itemCount: snapshot.data['messages']?.length ,
itemBuilder: (BuildContext context, int index){
return
ChatBubble(
clipper: ChatBubbleClipper1(type: BubbleType.receiverBubble),
backGroundColor: Color(0xffE7E7ED),
margin: EdgeInsets.only(top: 20),
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.7,
),
child: Text(
snapshot.data['messages'][index],
style: TextStyle(color: Colors.black),
),),);},),);}),],)
So one important thing to note is that Firebase "tables" aren't really like your RDBMS tables where you can have primary and foreign keys. You need to manage that manually. Simply store the ID of your primary key in every document that you create which you want to have a reference to the other "table".

Display document with variable true - Flutter Firebase

I have to show on the screen only the users that the ACTIVE variable is true. However I am not able to achieve this condition, it always displays all users registered in Firebase. How to do this for this code in question?
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: getListaPacientes(),
builder: (context, snapshot){
switch(snapshot.connectionState){
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.error_outline),
Text("Usuário não encontrado")
],
),
);
default:
List<DocumentSnapshot> documentos =
snapshot.data.documents;
return ListView.builder(
itemCount: documentos.length,
itemBuilder: (context, index){
return ListTile(
title: Text(items[index].nome,
style: TextStyle(fontSize: 16)),
subtitle: Text('Quarto: ${items[index].quarto}',
style: TextStyle(fontSize: 16)),
leading: CircleAvatar(
backgroundImage: NetworkImage(items[index].foto),
),
onTap: ()=> _navegarParaPerfil(context, items[index]),
);
}
);
}
}
),
)
Stream<QuerySnapshot> getListaPacientes(){
return Firestore.instance.collection('pacientes').snapshots();
}
What do you suggest to fix this imperfection? Thank you very much!
you can use the where API to retrieve the ACTIVE users from the firebase.
final CollectionReference collection =
FirebaseFirestore.instance.collection('employees');
Stream<QuerySnapshot> getStream() {
return collection.where('ACTIVE', isEqualTo: true).snapshots();
}

How to display any Data from Firestore using ternary operator

I was trying to fetch data from firebase and I wanted to show an Icon of Instagram only if there is any data available in the firebase collection. I used the following method to fetch the data from firebase
StreamBuilder(
stream: Firestore.instance.collection("aboutpage").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
child: Center(
child: SpinKitThreeBounce(
color: Colors.lightBlueAccent,
size: 30.0,
),
),
);
} else {
return Container(
child: ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot aboutpage = snapshot.data.documents[index];
return Column(
There is no Problem while retrieving data from firebase. Probleme is when I want to display an Instagram icon if the data is available in firebase is used ternary operator but did not work for me
"${aboutpage["name"]}" == null
? Container()
: IconButton(Icon: Icons.instagram),
onPressed: (}{}
),
I also tried using "${aboutpage["name"]}".isEmpty but dint work for me. So, How can I fetch data only if its available and if empty return empty Container?
Change the condition from "${aboutpage["name"]}" == null to aboutpage is Map && aboutpage["name"] == null.

Get information from Firebase and able to use it with a Gridtile and GestureDetector in Flutter

So I'm trying to design a Widget which can basically create a view where you can have something like this:
The problem that I'm facing is that for this example I used is calls to API's of Firebase, however, now I'm using the Firebase Auth and Firestore Extentionts and don't want to use the provider package or HTTP request, I have the following Firestore Collection:
As you see the collection name is users but inside has the user uid given by Firebase as a Document and inside that document has all the user Data.
So I need some help to have the following functionalities:
I need to create a ListView preferably ListView Builder so it can show the entire collection so it can display all the users contained in the collection. (Each user is a Document titled with his own User uid).
In the Tile, I want to display just name and Image but once it is clickable it should send me to a new page (the user profile page sending as an argument the uid)
I got this code: but I don't have the logic on how to get the list tile clickable and get the uid of the click user (in the tile) to send the info (uid) to the next page. But once I know how to display the contents of all the documents in the collection (displaying the name (nombre) inside each document as a title and how to capture the uid, I bet I can do the modifications and eliminations.
import 'package:flutter/material.dart';
import 'package:firebase_firestore/firebase_firestore.dart';
class ExpenseList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("users").snapshots,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text("No existe registros de Usuario");
return new ListView(children: getExpenseItems(snapshot));
});
}
getExpenseItems(AsyncSnapshot<QuerySnapshot> snapshot) {
return snapshot.data.documents
.map((doc) => ListTile(title: new Text(doc["nombre"], onTap: (){
//Here function to navigate to profile page saving the uid
}))
.toList();
}
}
In that list tile, I should have a Network image as I can have a parameter the image from the document in the collection.
Is there anything I can do?
Kind Regards.
Here you can find an example of a custom build ListView.
var futureBuilder=new FutureBuilder(
future: makecall.firebaseCalls(databaseReference), // async work
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none: return new Text('Press button to start');
case ConnectionState.waiting: return new Text('Loading....');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index){
return Card(
elevation: 0.0,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: SizedBox(
height: MediaQuery.of(context).size.height*0.15,
width: MediaQuery.of(context).size.width,
child: Card(
elevation: 0,
child: Row(
children: <Widget>[
new Container(
child: Image.network(snapshot.data[index].iconUrl,height: MediaQuery.of(context).size.width*0.3,width: MediaQuery.of(context).size.width*0.3,),
),
Padding(
padding: const EdgeInsets.only(left: 10,right: 5,top: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
condition('${snapshot.data[index].vegOrNon}')==true? new Image.asset('images/non_veg.png',height: 15,width: 15,): new Image.asset('images/veg.jpg',height: 15,width: 15),
SizedBox(width: 5),
Text(snapshot.data[index].foodtitle, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20,fontFamily: 'Roboto-Black'),)
],
),
SizedBox(height:10.0),
Row(
children: <Widget>[
new IconTheme(
data: new IconThemeData(
color: Colors.black26),
child: new Icon(Icons.timer,size: 20.0,),
),
Text('${snapshot.data[index].PreptimeInMins} minutes',style: TextStyle(fontWeight: FontWeight.w700,color: Colors.black26),),
],
),
],
)
],
),
),
],
),
),
],
)
)
),
),
);
},
);
}
},
);
I found this example on this guide and I think that it can be usefull for you.
If your issue is how to make a ListView tile clickable you can use the GestureDetector class to wrap your tile and send the UID in the .OnTap event

Cant get StreamBuilder to display data from cloud firestore

I know I have a connection to the database and no errors are appearing so I'm pretty confused. The title and code should summarize the problem fairly well. Think I'm missing something?
here is the main code that should be displaying cards with titles from firebase
mainList() {
StreamBuilder(
stream: Firestore.instance.collection('Events').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text('Loading');
} else {
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot userPost = snapshot.data.documents[index];
return Container(
width: MediaQuery.of(context).size.width,
height: 350.0,
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Material(
elevation: 14.0,
shadowColor: Color(0x802196F3),
child: Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: 200.0,
child: Text(
'${userPost['title']}',
))
],
),
),
))),
);
},
);
}
});
}
and here is where the function is called:
lass MyAppmain extends State<MyApp> {
#override
Widget build(BuildContext context) {
var listView = ListView.builder(
itemCount: local.length,
itemBuilder: (BuildContext cnxt, int index) {
return new Text(local[index]);
});
return MaterialApp(
home: PageView(
controller: controller,
children: <Widget>[
//home page---------------------------
Scaffold(
appBar: AppBar(
title: Text(
'Events',
),
elevation: 20,
),
//main list view for the cards
//think I use streambuilder for this so google before starting
body: mainList(),//RIGHT HERE
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(context, NewEventTransition());
},
mini: true,
),
),
//Profile Page-------------------------------
Scaffold(
appBar: AppBar(
title: Text(
'Profile',
),
elevation: 20,
),
),
],
));
}
}
Want a listview of cards holding the titles from firebase (will soon be more than titles but want to get this working first)
This is a common problem.
return ListView.builder(
itemCount: snapshot.data.documents.length, // this line is the culprit!
itemBuilder: (context, index) {
print(snapshot.data.documents.length); // it will print null
.......
}
See, It takes some time to fetch data from firebase. When ListView.builder is called the value of snapshot.data.documents.length is actually null. Tho after few seconds it gets data but till then ListView had built the UI and that's why it's blank. To check the value, you can add a Print statement like shown above.
Now there are few ways to solve this problem:
Make an int variable say totalLength, make a function say setTotalLength which makes a call to Firebase/Firestore database and use setState to assign this value to totalLength and then change that code to this:
itemCount: totalLength,
You should Call setTotalLength in your initState method.
Or, you can change your code to this, But I'm NOT 100% sure that this will work:
itemCount: snapshot.data.documents.length ?? 0 // returns 0 if the value is null, may reload UI again when data comes

Resources