Populate GridView from db in Flutter - database

I want to retrive data from table in db and display it into GridView in Flutter.
At the moment I display it in a simple List but I can't display it in GridView.
Here is my code
return Scaffold(
appBar: AppBar(
title: Text("Diario di bordo"),
),
/*body: Center(
child: Text('Nessun diario presente'),
),*/
body: FutureBuilder<List>(
future: dbHelper.queryAllRows(),
initialData: List(),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, int position) {
final item = snapshot.data[position];
//get your item data here ...
return Card(
color: RandomColor().randomColor(),
child: ListTile(
title: Text(
snapshot.data[position].row[1]),
),
);
},
)
: Center(
child: CircularProgressIndicator(),
);
},
),
...
I searched on documentation and I see this piece of code
GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
),
);
}),
);
I don't understand how retrive data from mytable in db and show it in GridView.

You can use the GridView.Builder
return snapshot.hasData?
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
final item = snapshot.data[index];
//get your item data here ...
return Card(
color: RandomColor().randomColor(),
child: ListTile(
title: Text(
snapshot.data[index].row[1]),
),
);
},
)
: Center(
child: CircularProgressIndicator(),
);

Related

I want to show current user data But it show empty screen

I want to show current user data but it show empty screen and also I print data it show null data printing data
This is my database database
This is my code
Container(
child: StreamBuilder(
stream: FirebaseFirestore.instance.collection("user3").where("id",isEqualTo:FirebaseAuth.instance.currentUser!.uid).snapshots(),
builder: (BuildContext context,AsyncSnapshot<QuerySnapshot> snapshot){
if(!snapshot.hasData){
return Text("Loading please wait........");
}
print(snapshot.data!.docs);
return Center(
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (BuildContext context, index) {
return
Text("Zohaib");
// Text(snapshot.data!.docs[index]["name"]);
},
)
),
],
),
);
},
),
),

Exclude documents from QuerySnapshot and Listview Builder (Flutter & Firebase)

I got a collection of questions in Firebase. The Categories are stored in an array. Now I want to to hide specific questions, if the user chose to hide it (User ID is stored in another array called hidden). This is what I tried:
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("question")
.where('category', arrayContainsAny: [widget.cid])
.where('hidden', '!=', '${user.uid}')
// also tried where('hidden', isNotEqualTo: [user.uid])
.snapshots(),
builder: (context, snapshot) {
return !snapshot.hasData
? Center(child: CircularProgressIndicator())
: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data!.docs[index];
return QuestionList(
de_du: data['de_du'],
de_sie: data['de_sie'],
de_ich: data['de_ich'],
qid: data['id'],
en: data['en'],
id: data.id,
documentSnapshot: data,
);
},
);
},
),
Any suggestions on how to get there?
Updated:
I tried to implement the transformation. I still get errors and do not get it to work. The errors I get: the first snapshot in transform is undefined. Expects an ) right after the first snapshot in transform. Also I get the info, that the user (provider of userid) is not used.
class _CategoryDetailState extends State<CategoryDetail> {
#override
Widget build(BuildContext context) {
var user = Provider.of<AuthProvider>(context);
return Scaffold(
appBar: AppBar(
title: Text(
this.widget.titel,
style: TextStyle(fontFamily: 'Gruppo'),
),
),
body: ListView(
children: [
Card(
margin: EdgeInsets.all(10),
child: Column(
children: [
Image.network(this.widget.image),
ListTile(
title: Text(this.widget.titel),
subtitle: Text(this.widget.description),
),
],
),
),
Center(
child: Text(
'Fragenübersicht:',
style: TextStyle(fontFamily: 'Caveat', fontSize: 25),
),
),
StreamBuilder<List<DocumentSnapshot>>(
stream: FirebaseFirestore.instance
.collection("question")
.where('category', arrayContainsAny: [widget.cid])
.snapshots()
.transform(snapshot => snapshot.docs.where(d => doc.data().hidden.contains(user.userid).toList())),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
return ListView.builder(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data![index];
return QuestionList(
de_du: data['de_du'],
de_sie: data['de_sie'],
de_ich: data['de_ich'],
qid: data['id'],
en: data['en'],
id: data.id,
documentSnapshot: data,
);
},
);
}
},
),
],
),
);
}
}
There is no way to exclude a single item from a Firestore query with a condition. What you'd need is an array-does-not-contain condition, which doesn't exist.
So that means that you'll have to read the additional items from the database, and then exclude them from the stream with something like:
StreamBuilder<List<DocumentSnapshot>>(
stream: FirebaseFirestore.instance
.collection("question")
.where('category', arrayContainsAny: [widget.cid])
.where('hidden', '!=', '${user.uid}')
.snapshots()
.transform(snapshot => snapshot.docs.where(d => doc.data().hidden.contains(user.uid)).toList(),
You'll need to update the builder too to reflect that it now gets List<DocumentSnapshot> instead of QuerySnapshot.

FutureBuilder and ListView.builder

Can someone please explain to me how to use itemCount from ListView.Builder which is inside of an FutureBuilder.
For now my FirebaseCloud Store only has one Document , and my app is returning an infinity list of documents,
I tried to use itemCount: snapshot.data.documents.length,
however, Get the error: Class 'DocumentSnapshot' has no instance getter 'documents'. Receiver: Instance of 'DocumentSnapshot' Tried calling: documents
EDIT it should only show this document one time and one of a kind if there is more than one document related to the UID
Here is my Code
final tabs = [
Center(
child: (Scaffold(
body: FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(uid)
.get(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.data == null)
return CircularProgressIndicator();
DocumentSnapshot manuais = snapshot.data;
if (snapshot.hasData) {
print('okkk');
print(manuais.data()['nome']);
} else {
print('nopeeeee');
}
return Container(
padding: EdgeInsets.all(16),
child: ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot manuais = snapshot.data;
return Card(
color: Colors.grey[250],
child: Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
new Image.asset(
'Images/pdflogo.png',
width: 32,
),
Center(
child: Text(
(manuais.data()['nome'].toString()),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 16),
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'Compartilhar / Download'),
onPressed: () async {
var request = await HttpClient()
.getUrl(Uri.parse(manuais
.data()['documento']));
var response =
await request.close();
Uint8List bytes =
await consolidateHttpClientResponseBytes(
response);
await Share.file(
'ESYS AMLOG',
'Manual.pdf',
bytes,
'image/jpg');
}),
],
),
],
),
),
);
}),
);
})))),
````
You have to do:
itemCount : 1
Since you are only retrieving one document, when you do:
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.get()
The above will always retrieve one document since the document id will always be unique.
You need to get length like this.
itemCount: snapshot.data.data().length,
if (snapshot.hasData) {
print('okkk');
print(manuais.data()['nome']);
return Container(
padding: EdgeInsets.all(16),
child: ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot manuais = snapshot.data;
return Card(
color: Colors.grey[250],
child: Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
new Image.asset(
'Images/pdflogo.png',
width: 32,
),
Center(
child: Text(
(manuais.data()['nome'].toString()),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 16),
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'Compartilhar / Download'),
onPressed: () async {
var request = await HttpClient()
.getUrl(Uri.parse(manuais
.data()['documento']));
var response =
await request.close();
Uint8List bytes =
await consolidateHttpClientResponseBytes(
response);
await Share.file(
'ESYS AMLOG',
'Manual.pdf',
bytes,
'image/jpg') ...(all your brackets go here)
}

Create a FeatureBuilder from Database in Flutter

I have saved my phone's call list to a database and now I want to create a ListView from this database. I have already written this code. But it is not working. what is wrong with my code?
database_helper.dart
...
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}
...
my_home.dart
...
FutureBuilder(
future: db.queryAllRows(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
List entries = snapshot.data.toList();
return Scrollbar(
child: ListView.builder(
itemBuilder: (context, index) {
var entry = entries[index];
var mono = TextStyle(fontFamily: 'monospace');
return Column(
children: <Widget>[
Divider(),
Text('NUMBER : ${entry.number}', style: mono),
Text('NAME : ${entry.name}', style: mono),
Text('TYPE : ${entry.callType}', style: mono),
Text(
'DATE : ${DateTime.fromMillisecondsSinceEpoch(entry.timestamp)}',
style: mono),
Text('DURATION : ${entry.duration}',
style: mono),
],
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
);
},
itemCount: entries.length,
),
);
})
...
You need to use ConnectionState inside your builder. Look at this code template: (Currently the builder return your widget without waiting for the future to complete)
return FutureBuilder<List<Map<String, dynamic>>>(
future: db.queryAllRows(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// future complete
if (snapshot.hasError || !snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
// future complete with no error and has data
List entries = snapshot.data.toList();
return Scrollbar(
child: ListView.builder(
itemBuilder: (context, index) {
var entry = entries[index];
var mono = TextStyle(fontFamily: 'monospace');
return Column(
children: <Widget>[
Divider(),
Text('NUMBER : ${entry.number}', style: mono),
Text('NAME : ${entry.name}', style: mono),
Text('TYPE : ${entry.callType}', style: mono),
Text(
'DATE : ${DateTime.fromMillisecondsSinceEpoch(entry.timestamp)}',
style: mono),
Text('DURATION : ${entry.duration}', style: mono),
],
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
);
},
itemCount: entries.length,
),
);
}
// return loading widget while connection state is active
else {
return Center(child: CircularProgressIndicator());
}
});

How to refer to a variable in a Firebase server which belongs to a particular document?

Background: I'm writing an app in which you can store the plus points and fives of a class.
I do this with Flutter and Firebase. My Firestore database collection is called 'mates' and it has several documents, with a unique, auto-ID. Every document has three fields: a name(string), points(number), fives(number).
I have made this far with the help of this tutorial: https://www.youtube.com/watch?v=DqJ_KjFzL9I&t=591s
I want to modify the GUI a bit, in each listtile I display the name, button for decrementing points, the value of points, button for incrementing points, button for decrementing fives, value of fives, button for incrementing fives and a button for setting the value of fives to zero.
My question would be, that how can I refer to the fields(points, fives) of the database when changing their values?
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Widget _buildListItem(BuildContext context, DocumentSnapshot document){
return ListTile(
title: Row(
children: [
Expanded(
child: Text(
document["Name"],
style: Theme.of(context).textTheme.headline,
)
),
Container(
decoration: const BoxDecoration(
color: Color(0xffddddff)
),
padding: const EdgeInsets.all(10.0),
child: Text(
document['Points'].toString(),
style: Theme.of(context).textTheme.display1,
),
),
Container(
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.keyboard_arrow_left),
iconSize: 30,
onPressed: (){
setState(() {
if(points!=0) { //I mean here
points--; //I mean here
}
});
}
),
Text(
"$points", //I mean here
style: TextStyle(
fontSize: 30
),
),
IconButton(
icon: Icon(Icons.keyboard_arrow_right),
iconSize: 30,
onPressed: (){
setState(() {
points++; //I mean here
if(points==10){ //I mean here
points=0; //I mean here
fives++; //I mean here
}
});
}
),
Text(
"$fives", //I mean here
style: TextStyle(
fontSize: 30
),
),
IconButton(
icon: Icon(Icons.check_circle),
iconSize: 30,
onPressed: (){
setState(() {
fives=0; //I mean here
});
}
),
]
)
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Center(
child: Scaffold(
appBar: AppBar(
title: Text("Punkte++"),
centerTitle: true,
),
body: StreamBuilder(
stream: Firestore.instance.collection("mates").snapshots(),
builder: (context, snapshot) {
if(!snapshot.hasData) return const Text("Loading...");
return ListView.builder(
itemExtent: 80.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildListItem(context, snapshot.data.documents[index]),
);
}
),
)
);
}
}

Resources