I'm making a conversation starter app and inside this app, there are different categories of questions a user can choose from. This is how the home page of the app looks like after the user logs in:
The way I'm currently listing all these categories is by saving the category names as the document ID's under a collection I call 'users'. Then I use the following snippet of code to get all these document IDs/ categories and add them to a List
. I then use a FutureBuilder
to convert this List<String>
to a List
of buttons. The code below can help clarify what I am doing:
Step 1: get all document IDs/category names:
List<String> questionCategories = [];
Future getCategories() async {
await FirebaseFirestore.instance
.collection('users')
.get()
.then((snapshot) => snapshot.docs.forEach(
(document) {
questionCategories.add(document.reference.id);
));
}
Step 2: Use the questionCategories List<String>
to create a List
of buttons
FutureBuilder(
future: getCategories(),
builder: (context, snapshot) {
return SizedBox(
height: MediaQuery.of(context).size.height - 250,
child: ListView.builder(
itemCount: questionCategories.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: //questionPageInit,
() {
print(collectionList);
Navigator.push(context,
MaterialPageRoute(builder: (context) {
//return ForgotPasswordPage();
return CategoryPage(
categoryName: questionCategories[index],
);
}));
},
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Text(questionCategories[index],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
))))),
);
},
),
);
},
),
Upon picking a category, questions are displayed one at a time on a question card, wherein below this card a user can switch between the next and previous questions and then shuffle. This page looks like so:
The way I'm getting these questions displayed is by getting a List
of all the fields under a document ID and adding it to a List<String>
. When the user presses shuffle, next, or previous, I just change a global index variable and set the state again to display a new question based on which question appears to be at that specific index in the List
. The following code should help clarify what I am doing:
void printAllQuestionsList(snapshot) {
Map<String, dynamic> data = snapshot.data() as Map<String, dynamic>;
for (String key in data.keys) {
print(key + data[key]!);
questionsList.add(data[key]);
}
}
Future getQuestionList() async {
if (questIndex > 1) {
return;
}
if (widget.categoryName == "ALL") {
await FirebaseFirestore.instance
.collection('users')
.get()
.then(((snapshot) => snapshot.docs.forEach((document) {
print(document.reference.id);
FirebaseFirestore.instance
.collection('users')
.doc(document.reference.id)
.get()
.then((snapshot) => {printAllQuestionsList(snapshot)});
})));
} else {
await FirebaseFirestore.instance
.collection('users')
.doc(widget.categoryName)
.get()
.then((snapshot) => {printQuestionList(snapshot)});
}
}
Inside the widget Build function, I have this snippet of code:
FutureBuilder(
future: getQuestionList(),
builder: ((context, snapshot) {
// return TextField(
// decoration: InputDecoration(
// enabledBorder: OutlineInputBorder(
// borderSide: BorderSide(
// width: 5, //<-- SEE HERE
// color: Colors.greenAccent,
// ),
// borderRadius: BorderRadius.circular(50.0),
// ),
// ),
// );f
return Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.all(10.0),
width: 350,
height: 350,
decoration: BoxDecoration(
color: Colors.deepPurple[200],
borderRadius:
BorderRadius.all(Radius.circular(20))
// border: Border.all(color: Colors.blueAccent)
),
child: Align(
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Text(
questionsList[index],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 32,
),
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
),
),
));
}))
I have a second page on this app that is used to submit questions to an existing or new Category
(if they enter the right password that I set).
I use the following snippet of code to do so:
Future addQuestion(String category, String question) async {
var usersRef = questionCollection.doc(category);
await FirebaseFirestore.instance
.collection('users')
.get()
.then((snapshot) => snapshot.docs.forEach(
(document) {
existingQuestionCategories.add(document.reference.id);
},
));
if (existingQuestionCategories.contains(category)) {
print("Document Exists! ");
questionCollection.doc(category).update({question: question});
} else {
// FieldPath pathfield = FieldPath.fromString(category);
//String category2 = pathfield.category;
print('No such document exists so now about to set document anew!');
print(category);
FirebaseFirestore.instance
.collection("users")
.doc(category)
.set({question: question});
}
}
Here's how my Firestore database is organized
Users -> Question Categories (Document IDs) -> question Key: question field
This is how I want to set it up:
Users -> Autogenerated ID -> Question Categories as collections -> question key (titled “question”): question key (“the actual question here)
This way under each collection I can also list fields pertaining to the question like if it's light, medium, or deep that I may be able to add on to later.
I also want to do it this way because sometimes when I try to use my submit question page, the question I type does not get submitted and I think it may be because I'm submitting the question under a document ID and not under a collection.
In summary, my question to you is how do I list all the questions on my home page as a list of collections from my database? Also, how would this change the code I wrote to (1) view the questions on individual cards when clicking a category name and (2) submit new questions to a specific category/collection? If what I'm trying to do cannot be done in the way I want it done, is there a more efficient way to do this?
I tried searching for how to get a list of collections on Firestore on Flutter but all the answers I found gave me a solution on how to get a List
of fields under a document ID. This is why I'm asking this question.
Actually the Firebase SDK for Flutter ( and I'm assuming that for Android/IOS) doesn't have any pre-built methods to get a List
of all collections in the firestore database.
But, as I know you can get them with a cloud function written as example with Node.js
, refer to this and this .
if you're willing to write a cloud function to achieve this on your flutter project, then it's fine.
However, I can think about a practical solution, if that interest's you:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.