get a document from firestore with a required phone number - flutter

I have a collection of users in have created docs names as per their UID and each doc has a field "phoneNumber" , I want to get a SINGLE Document
In numberArray i have some selected numbers to be searched
ListView.builder(
itemCount: number.length,
itemBuilder: (context, index) => FutureBuilder(
future: FirebaseFirestore.instance
.collection("Users")
.where('phone', isEqualTo: number[index])
.get(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData && snapshot.data != null) {
return ListTile();
else return Container();

Related

my Querysnapshot Map String become AsyncSnapshot<Object> with no reason

I have a streamBuilder where the "snapshots()" change from Stream<QuerySnapshot<Map<String, dynamic>>> to AsyncSnapshot<Object?>.
This is weird because I have another app, with identical code and works fine.
The problem is, I cannot access "snapshot.data.docs" and all firestore datas.
Why is happening?
my code:
body: StreamBuilder(
//Stream<QuerySnapshot<Map<String, dynamic>>>
stream: firestore.collection('Books').orderBy('name').snapshots(),
//AsyncSnapshot<Object?>
builder: (context, snapshot ) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(child: CircularProgressIndicator());
{
final document = snapshot.data?; //error here
return ListView.builder(
itemCount: document?.length,
itemBuilder: (context, index) {
return Column(
Declare your StreamBuilder Widget response type as a dynamic, and you should use
snapshot.data.docs without any problem.
body: StreamBuilder<dynamic>(
stream: FirebaseFirestore.instance.collection('Books').orderBy('name').snapshots(),
builder: (context, snapshots) {
if(snapshots.hasData){
print(snapshots.data.docs.toString());
}});

Wait a function to be done in ListView

I need to wait my function to be done in a ListView because of a Firestore request. I tried using Future.wait() but it does not work.
FutureBuilder<QuerySnapshot>(
future: FirebaseFirestore.instance
.collection('Statements')
.where('userID',isEqualTo: context.watch<User>().uid)
.get(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if (snapshot.hasError) {return Text("Erreur");}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");}
return Expanded(
child:ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot document = snapshot.data.docs[index];
Future.wait([getStatementData(document)]);
return StatementCard(statement:selectedStatement,
accommodation : relatedAccommodation,
owner : relatedOwner);
},
)
Here is the function called :
Future getStatementData(document) async {
selectedStatement = Statement.fromFirebase(document);
document.data()["accommodation"].get().then((value) {
relatedAccommodation = Accommodation.fromFirebase(value);});
await FirebaseFirestore.instance
.collection('Owners')
.doc(document["ownerList"][0])
.get().then((value) {
print(value.data());
relatedOwner = Owner.fromFirebase(value);
});
}
Should I use another future builder ?
You should do it like this by returning another Future Builder inside :
ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot document = snapshot.data.docs[index];
return FutureBuilder(
future: getStatementData(document) ,
builder: (context, snapshot) {
return snapshot.connectionState == ConnectionState.done
? StatementCard(statement:selectedStatement,
accommodation : relatedAccommodation,
owner : relatedOwner);
: Container();
);
},
)
I think you just missed a simple thing, FutureBuilder also has a connectionstate.done state which you can access. This waits until your future function is Done.
return FutureBuilder(
future: yourFunction,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Center(child: Text('No status',);
break;
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
break;
case ConnectionState.done:
return Text('Im done!') // Your listviewbuilder comes here
break;
default:
}
},
),
doc: https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
example FutureBuilder with ListViewBuilder: https://medium.com/nonstopio/flutter-future-builder-with-list-view-builder-d7212314e8c9
[...]connectionState.done = [future] is not null, and has completed. If the future completed successfully, the [AsyncSnapshot.data] will be set to the value to which the future completed. If it completed with an error, [AsyncSnapshot.hasError] will be true and [AsyncSnapshot.error] will be set to the error object.[...]

How do I get only the current users posts to show?

I'm trying to build an app in flutter and I have come up against this problem which I can't seem to find any existing answers. How do I get only the current users posts to show? My posts collection has a user id field which I want to compare with the current user and display only the post where the userId and currentUser are the same.
return FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (ctx, futureSnapshot) {
if (futureSnapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return StreamBuilder(
stream: Firestore.instance.collection('posts').snapshots(),
builder: (context, streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
final documents = streamSnapshot.data.documents;
return ListView.builder(
itemCount: documents.length,
itemBuilder: (ctx, index) => PostItem(
documents[index]['title'],
documents[index]['imageUrl'],
documents[index]['location']['address'],
));
});
});
here is my post collection structure
You're currently getting all posts with:
Firestore.instance.collection('posts').snapshots()
If you only want posts for the current user, that'd be something like:
var uid = (await FirebaseAuth.instance.currentUser()).uid;
Firestore.instance.collection('posts').where('uid', isEqualTo: uid).snapshots()
The first line determines the UID of the current user, and then the second line uses that to request only documents whose uid field matches the value.
I just realised I hadn't but my future into a variable for the streambuilder where clause !! I was trying to use the original fireauth currentuser!
return FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (ctx, futureSnapshot) {
if (futureSnapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
**final String currentUser** = futureSnapshot.data.uid;
return StreamBuilder(
stream: Firestore.instance
.collection('posts')
.where('userId', isEqualTo: **currentUser**)
.snapshots(),
builder: (context, streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
final documents = streamSnapshot.data.documents;
return ListView.builder(
itemCount: documents.length,
itemBuilder: (ctx, index) => PostItem(
documents[index]['userId'],
documents[index]['title'],
documents[index]['imageUrl'],
documents[index]['location']['address'],
));
});
});
```

FutureBuilder doesn't work properly with Firestore

can't create a query using FutureBuilder.
Firestore is at the latest version.
This is the case for both Android and iOS devices, any ideas?
return FutureBuilder<QuerySnapshot>(
future: Firestore.instance
.collection('productlist')
.where('productid', isEqualTo: pid)
.limit(
1), // a previously-obtained Future<String> or null
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
productname = snapshot.data.documents[0]['productname'];
print("productname:" + productname);
}
else{
productname = "0";
}
},
);
I think the issue here is that you are not returning a widget.
Try the code below
FutureBuilder(
future: Firestore.instance
.collection('productlist')
.where('productid', isEqualTo: pid)
.limit(1),
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
return Text(snapshot.data.documents[0]['productname']);
} else {
return Text("0");
}
},
),
u can use stream builder instead it works pretty well :
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('productlist').where('productid', isEqualTo: pid).limit(1),
builder: (context, snapshot) {
if (snapshot.data != null) {
// Here u will get list of document snapshots
final List<DocumentSnapshot> documents = snapshot.data.documents;
// now u can access each document by simply specifying its number
// u can also use list view to display every one of them
return ListView.builder(
itemCount: documents.length,
itemBuilder: (context, int index) => Text(documents[index]['productname']),
);
} else {
// Show loading indicator here
}
},
);

Flutter/Dart How can I have two e two isGreaterThanOrEqualTo in one field in a QuerySnapshot?

I want from a collection of firestore only these files in the Futerbuilder have both the same data.But it does not work. Apparently it's because I used two isGreaterThanOrEqualTo.
How can I use two isGreaterThanOrEqualTo in one field?
Future getData() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection(tag).where('ckey', isGreaterThanOrEqualTo: 1).where('dkey', isGreaterThanOrEqualTo: 1).getDocuments();
return qn.documents;
}
...
void initState() {
super.initState();
_data = getPosts();
}
...
FutureBuilder(
future: _data
builder: (context, projectSnap)
...
return ListView.builder(
itemCount: projectSnap.data.length,
itemBuilder: (context, index)
NoSuchMethodError: The getter 'length' was called on null
You have NoSuchMethodError: The getter 'length' was called on null, because FutureBuilder's snapshot data will be null until the future is resolved.
You can either provide initialData:
FutureBuilder(
future: _data,
initialData: [],
builder: (context, projectSnap) {
...
return ListView.builder(
itemCount: projectSnap.data.length,
itemBuilder: (context, index)
or check if data exists inside builder:
FutureBuilder(
future: _data,
builder: (context, projectSnap) {
if (!projectSnap.hasData) return Container();
...
return ListView.builder(
itemCount: projectSnap.data.length,
itemBuilder: (context, index)