the idea is that i am trying to display "rules of a challenge" inside a container in my flutter app, i was able to get all the challenge information such as name, description, and other info.
first take a look at my database and the collection that contains the challenges:
"rules" is the array that i am trying to retrieve,
here is the data fetching function :
List _challenges = [];
fetchChallengeData() async {
var _fireStoreInstance = FirebaseFirestore.instance;
QuerySnapshot qn = await _fireStoreInstance.collection("challenges").get();
setState(() {
for (int i = 0; i < qn.docs.length; i ) {
_challenges.add({
"image-path": qn.docs[i]["image-path"],
"description": qn.docs[i]["description"],
"name": qn.docs[i]["name"],
"date": qn.docs[i]["date"],
"isTeam": qn.docs[i]["isTeam"],
"price": qn.docs[i]["price"],
"prize": qn.docs[i]["prize"],
});
}
});
}
as you see the function is iterating documents (challenges) inside the collection, each document have the data showed above and it is added to a list declared in the code.
now after fetching the data i will pass it to another screen and display the rules in this function:
challengeRules(String title, String desc) {
return Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
color: Colors.purple,
height: 35,
child: Center(
child: Text(
title,
style: TextStyle(
color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
)),
),
Container(
padding: EdgeInsets.all(15),
width: MediaQuery.of(context).size.width,
child: Directionality(
textDirection: TextDirection.rtl,
child: Text(
desc,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, height: 1.8, letterSpacing: 1),
),
),
),
],
);
}
when i display any data i fetched i use for example widget._challenges['name']
and it display the data normally, in the last code "desc" is the variable that will hold the array value.
so my questions are, how to fetch the array information with the fetching function am using, and how to display and render the array data?, ill be thankful for any help.
CodePudding user response:
Well the rules just look like a list of strings, so something similar to your other fields:
add({
...
"prize" ... etc,
// Create a list of strings from the rules key and fallback to an empty list when that doesn't exist.
"rules": List<String>.from(qn.docs[i]["rules"] ?? []),
});
And then to display them something like:
Widget challengeRules(String title, String description, List<String> rules) {
return Column(
children: [
Text(title),
Text(description),
// [...] is the spread operator that combines the lists
// [.map] iterates over every item in the list and returns a text widget
...rules.map((rule) => Text(rule)).toList(),
],
);
}
I would highly suggest working with a backing models for your firestore documents. So that your calling sites can looks something more like this:
final db = FirebaseFirestore.instance;
QuerySnapshot snapshot = await db.collection("challenges").get();
setState(() {
challenges = snapshot.docs.map((doc) => Challenge.fromMap(doc)).toList();
});
The challenge model is a class that looks like your firestore document
class Challenge {
Challenge({required this.image, required this.path, required this.isTeam ... etc.});
String image;
String path;
String isTeam;
... etc.
static Challenge fromMap(Map<String, dynamic> data){
return Challenge(
image: data['image'],
path: data['path'],
isTeam: data['isTeam'],
... etc.
);
}
}
And then just passing your Challenge model around, something like:
Widget challengeRules(Challenge challenge) {
return Column(
children: [
Text(challenge.title),
Text(challenge.description),
...challenge.rules.map((rule) => Text(rule)).toList(),
],
);
}
I'd also recommend that the method just be turned into a stateless widget: https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
...
child: ChallengeViewWidget(challenge: challenge),