i want to create list from firestore data
to add suggestions/autocomplete in text field, any help please?
example list:
static final List<String> commodity = [
'Banana',
'Mango',
'Orange',
];
wanted list from firestore:
static getSuggestion(String suggestion) async =>
await FirebaseFirestore.instance
.collection("QFS")
.where('commodity', isEqualTo: suggestion)
.get()
.then((snap) {
return snap.docs;
});
}
my whole code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var _selectedCommodity1;
var _selectedCommodity2;
TextEditingController commodityFiled1 = TextEditingController();
TextEditingController commodityFiled2 = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text("QFS"),
),
body: Form(
child: Container(
padding: const EdgeInsets.only(
top: 5, bottom: 10, right: 20, left: 20),
child: Column(children: [
TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
controller: commodityFiled1,
decoration: const InputDecoration(
labelText: 'Commodity1',
icon: Icon(
Icons.receipt_rounded,
color: Colors.black87,
))),
suggestionsCallback: (pattern) {
return CommodityService.getSuggestions(pattern);
},
itemBuilder: (context, String suggestion) {
return ListTile(
title: Text(suggestion),
);
},
transitionBuilder:
(context, suggestionsBox, controller) {
return suggestionsBox;
},
onSuggestionSelected: (String suggestion) {
commodityFiled1.text = suggestion;
},
onSaved: (value) => _selectedCommodity1 = value!,
),
TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
controller: commodityFiled2,
decoration: const InputDecoration(
labelText: 'Commodity2',
icon: Icon(
Icons.receipt_rounded,
color: Colors.black87,
))),
suggestionsCallback: (pattern) {
return getSuggestion(pattern);
},
itemBuilder: (context, dynamic suggestion) {
return ListTile(
title: Text(suggestion),
);
},
transitionBuilder:
(context, suggestionsBox, controller) {
return suggestionsBox;
},
onSuggestionSelected: (dynamic suggestion) {
commodityFiled2.text = suggestion;
},
onSaved: (value) => _selectedCommodity2 = value!,
),
])))));
}
static getSuggestion(String suggestion) async =>
await FirebaseFirestore.instance
.collection("QFS")
.where('commodity', isEqualTo: suggestion)
.get()
.then((snap) {
return snap.docs;
});
}
class CommodityService {
static final List<String> commodity = [
'Banana',
'Mango',
'Orange',
];
static List<String> getSuggestions(String query) {
List<String> matches = [];
matches.addAll(commodity);
matches.retainWhere((s) => s.toLowerCase().contains(query.toLowerCase()));
return matches;
}
}
Clarification: From my understanding, you have documents in your collection that each of them has the property commodity (type String) and you want to fetch only the document that has a specific commodity.
Open your Google Firestore Database dashboard and check which types you can have the documents of your collection.
Click Add document to check the types.
Check the Firestore docs.
Inside snapshot.data, there's docs (every document of your collection).
The code is from docs:
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _usersStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['full_name']),
subtitle: Text(data['company']),
);
}).toList(),
);
},
);
}
The code above shows how to convert every document (type DocumentSnapshot) to a JSON format (that can be represented with Map<String, dynamic>). To access to your field commodity (type String), put this data['commodity']. For doc id, you'll need access with document.id, because it isn't inside the document.data() method.
Then on suggestionCallback (I read TypeAheadField of flutter_typeahead API, you have to return to it a List (it's an Iterable) of some type (like List<String>).
I never tried this Flutter package before, but I would edit getSuggestion():
static Future<List<String>> getSuggestion(String suggestion) async =>
return await FirebaseFirestore.instance
.collection("QFS")
.where('commodity', isEqualTo: suggestion)
.get()
.then((snap) {
final docs = snap.data!.docs;
return docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return data['<fieldname of your document, e.g., "country" or "commodity"'];
}).toList(),
});
Write your solution on comments section.
Related
I started learning flutter isar yesterday and I couldn't love it more. I created a demo app with it and for some reason, it is not working as expected.
The app has two sections: Original(This contain the dummyData) and the Database(this contains data in the isar database).
When an item is starred in the original, it is added in the database and the icon is changed to filled_star. When the item is unstarred in the original section, it is expected to be removed from the database section and the icon is expected to change to star_outline. This is works fine.
However, when the app is hot-restarted, I am unable to unstar the items. Check the GIF below.
main.dart
import 'package:flutter/material.dart';
import 'package:isardemo/isar_files/course.dart';
import 'package:isardemo/isar_files/isar.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blueGrey,
),
home: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final dummyData = [
Course()
..title = 'MTH 212'
..courseId = '1ab',
Course()
..title = 'STS 432'
..courseId = '2bc',
Course()
..title = 'SHS 555'
..courseId = '3de',
Course()
..title = 'HMM 999'
..courseId = '4fg',
Course()
..title = 'EEE 666'
..courseId = '5hi',
];
Future<void> onFavTap(IsarService courseData, Course course) async {
if (await courseData.isItemDuplicate(course)) {
await courseData.deleteCourse(course);
setState(() {});
debugPrint('${course.courseId} deleted');
} else {
await courseData.addCourse(course);
setState(() {});
debugPrint('${course.courseId} added');
}
}
final courseData = IsarService();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Isar'),
),
body: ListView(
padding: const EdgeInsets.all(20),
children: [
Center(
child: FutureBuilder(
initialData: courseData,
future: courseData.favoritesCount(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style:
const TextStyle(fontSize: 25, color: Colors.lightGreen),
);
} else {
return const LinearProgressIndicator();
}
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
courseData.cleanDb();
setState(() {});
},
child: const Text('Destroy Database')),
),
const Text('Original',
style: TextStyle(fontSize: 30, color: Colors.green)),
ListView.separated(
shrinkWrap: true,
separatorBuilder: (context, index) => const SizedBox(height: 5),
itemCount: dummyData.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
tileColor: Colors.blueGrey,
title: Text(dummyData[index].title),
trailing: IconButton(
icon: FutureBuilder(
// initialData: courseData.isItemDuplicate(dummyData[index]),
future: courseData.isItemDuplicate(dummyData[index]),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data) {
return const Icon(Icons.star);
} else {
return const Icon(Icons.star_border_outlined);
}
}
return const Icon(Icons.g_mobiledata,
color: Colors.green);
},
),
onPressed: () => onFavTap(courseData, dummyData[index])),
);
},
),
const SizedBox(height: 20),
const Text(
'database',
style: TextStyle(fontSize: 30, color: Colors.green),
),
FutureBuilder(
future: courseData.getAllCourses(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data![index].title),
trailing: InkWell(
onTap: () async {
await courseData
.deleteCourse(snapshot.data![index]);
setState(() {});
},
child: const Icon(Icons.star)),
);
},
);
} else {
return const Center(
child: LinearProgressIndicator(),
);
}
}),
],
),
);
}
}
course.dart
import 'package:isar/isar.dart';
part 'course.g.dart';
#Collection()
class Course {
Id id = Isar.autoIncrement;
late String courseId;
late String title;
late bool isFavorite = false; // new property
}
isar.dart
import 'package:path_provider/path_provider.dart';
import 'course.dart';
class IsarService {
late Future<Isar> _db;
IsarService() {
_db = openIsar();
}
Future<Isar> openIsar() async {
if (Isar.instanceNames.isEmpty) {
final directory = await getApplicationDocumentsDirectory();
return await Isar.open([CourseSchema],
inspector: true, directory: directory.path);
} else {
return await Future.value(Isar.getInstance());
}
}
Future<void> addCourse(Course course) async {
final isar = await _db;
await isar.writeTxn(() async {
await isar.courses.put(course);
});
}
Future<bool> isItemDuplicate(Course course) async {
final isar = await _db;
final count =
await isar.courses.filter().courseIdContains(course.courseId).count();
return count > 0;
}
Future<List<Course>> getAllCourses() async {
final isar = await _db;
return isar.courses.where().findAll();
}
Future<void> deleteCourse(Course course) async {
final isar = await _db;
await isar.writeTxn(() async {
await isar.courses.delete(course.id);
});
}
Future<String> favoritesCount() async {
final isar = await _db;
final count = await isar.courses.count();
return count.toString();
}
Future<void> cleanDb() async {
final isar = await _db;
await isar.writeTxn(() => isar.clear());
}
}
I tried downgrading the isar version but it didn't work.
I fixed it! Instead of auto-incrementing the id, I used the Course's id instead. But Id expects an integer so I had to convert the Course's id into an integer using the fastHash.
Learn more
course.dart
#Collection()
class Course {
late String id;
Id get courseId => fastHash(id);
late String title;
}
int fastHash(String string) {
var hash = 0xcbf29ce484222325;
var i = 0;
while (i < string.length) {
final codeUnit = string.codeUnitAt(i++);
hash ^= codeUnit >> 8;
hash *= 0x100000001b3;
hash ^= codeUnit & 0xFF;
hash *= 0x100000001b3;
}
return hash;
}
Is there anyway to get a future when displaying a list?
I have list with two user id's ( one of them is the userlogged in, the other one is the user to chat with ).
my goal is to get and display the other users name in the chat.
the issue I am running into, is that you cant do async functions within the list
how can i fix this?
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
var otherUserName = await getOtherUsersName(job.userIdsArr);
;
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
I tried the following code as suggested but did not work::
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../../services/auth/auth_service.dart';
import '../../services/cloud/cloud_chat.dart';
import '../../services/cloud/cloud_storage_constants.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
The simple and short answer is to use FutureBuilder which take future as named parameter and give you the result in builders parameters generally know as snapshot.
First of all wrap your list view with future builder :
FutureBuilder(
future: "you future funtion here",
builder: (context, snapshot) {
return ListView.builder(itemBuilder: itemBuilder);
}
)
now you can give future funtion , in your case it is
FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
And remember to use snapshot if conditions for loading and empty data
complete code
import 'package:flutter/material.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
HopeFully It will help you.
The code below is what I am trying now. The page works does everything I need but now I need this database reference to use the loanuid, clientuid, and companyName to get to the right directory.
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('prosperitybank')
.doc('OHViYK8Zz6XfKGJsSXRL')
.collection('Project Information')
.snapshots()```
I need it from my collection.(userCreationRef).doc(loggedinuid) as shown in the picture. I can not figure out how to do this without the stream builders interfering any help would be greatly appreciated. I have tried to using this to help but it did not How can you nest StreamBuilders in Flutter?. I also tried looking at the documentation here https://firebase.flutter.dev/docs/firestore/usage/.
Picture of Document I need data fields from
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:photoloanupdated/screens/mains/viewproperties.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
final FirebaseAuth auth = FirebaseAuth.instance;
final user = auth.currentUser;
final uid = user?.uid;
var users = FirebaseFirestore.instance.collection('userCreationRequests');
var companyname = "";
return Scaffold(
appBar: AppBar(
title: Text(companyname),
),
body:
FutureBuilder<DocumentSnapshot>(
future: users.doc(uid).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text("Full Name: ${data['companyName']} ${data['last_name']}");
}
return Text("loading");
},
);
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('prosperitybank')
.doc('OHViYK8Zz6XfKGJsSXRL')
.collection('Project Information')
.snapshots(), //key spot fV or email fix
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data?.docs.length,
itemBuilder: (BuildContext context, int index) {
QueryDocumentSnapshot<Object?>? documentSnapshot =
snapshot.data?.docs[index];
//for date/time DateTime mydateTime = documentSnapshot['created'].toDate();
return InkWell(
onTap: () {
Navigator.of(context)
.push(
MaterialPageRoute(
builder: (context) => ViewProperties(documentSnapshot,
snapshot.data?.docs[index].reference)),
)
.then((value) {
setState(() {});
});
},
child: Card(
child: Container(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${documentSnapshot!['address']}",
style: TextStyle(
fontSize: 24.0,
fontFamily: "lato",
fontWeight: FontWeight.bold,
color: Colors.black),
),
Container(
alignment: Alignment.centerRight,
child: Text(
"${documentSnapshot!['projectcomplete'].toString() + "% Complete"}",
// for mydateTime.toString(),
style: TextStyle(
fontSize: 17.0,
fontFamily: "lato",
color: Colors.black87),
),
)
],
),
),
),
),
);
},
);
} else {
return Center(
child: Text("Loading..."),
);
}
},
),
);
}
}
String uuid;
Future<List<Map<String, dynamic>>> _onQuery() {
Future<List<Map<String, dynamic>>> res;
if (uuid != null) {
res = future.get().then((v) => v.docs
.map((e) => e.data())
.where((e) =>
e['uuid'].toLowerCase().contains(uuid))
.toList());
} else {
res = future.get().then((v) => v.docs.map((e) => e.data()).toList());
}
setState(() {});
return res;
}
now you can use _onQuery as stream.
I have two screens, 1st the ViewStudent screen has basic data about a student. I am displaying the data inside a ListView builder. Each item inside the ListView builder has an on-tap function that goes to another screen, StudentDetails. I am able to read data from the firestore collection named 'student'. There is another collection named 'currentRecord' where I am adding the id from the 'student' collection as a reference.
When a user clicks on the ViewStudent Listview builder item, it needs to read data from the 'currentRecord' collection according to the index and display that data inside the 'StudentDetails' screen. FYI I am using Getx.
Method to Read data from 'student' collection.
Stream<List<StudentModel>> getAllStudents() => _firestore
.collection(FirestoreConstants.pathUserCollection)
.doc(_firebaseAuth.currentUser!.uid)
.collection(FirestoreConstants.pathStudentCollection)
.orderBy(FirestoreConstants.studentName)
.snapshots()
.map((query) =>
query.docs.map((e) => StudentModel.fromSnapshot(e)).toList());
Method to read data from 'currentRecord' collection.
Stream<List<CurrentHifzRecordModel>> getCurrentRecords() {
var studentId = _firestore
.collection(FirestoreConstants.pathUserCollection)
.doc(_firebaseAuth.currentUser!.uid)
.collection(FirestoreConstants.pathStudentCollection)
.doc('documentId')
.get();
return _firestore
.collection(FirestoreConstants.pathUserCollection)
.doc(_firebaseAuth.currentUser!.uid)
.collection(FirestoreConstants.pathCurrentRDCollection)
.where(FirestoreConstants.studentId, isEqualTo: studentId)
.snapshots()
.map((query) => query.docs
.map((e) => CurrentHifzRecordModel.fromSnapshot(e))
.toList());
Displaying data from 'student' collection in ViewStudent screen.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: customAppBar('Students', context),
body: Obx(
() {
return ListView.separated(
itemCount: controller.students.length,
itemBuilder: (context, index) {
return GFListTile(
icon: const Icon(Icons.arrow_forward_ios),
avatar: GFAvatar(
backgroundColor: AppColors.indyBlue,
size: GFSize.SMALL,
child: Text(
controller.students[index].studentName![0],
style: const TextStyle(
fontSize: Sizes.dimen_22, fontWeight: FontWeight.bold),
),
),
titleText:
'${controller.students[index].studentName!} ${controller.students[index].fatherName!} ${controller.students[index].surname!}',
subTitleText:
'${controller.students[index].studentClass!} Division: ${controller.students[index].classDivision}',
onTap: () {
Get.toNamed(Routes.studentDetails);
},
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
);
},
),
Trying to display data from 'currentRecord' collection to StudentDetail screen based on index from ViewStudent screen on click on individual item.
#override
Widget build(BuildContext context) {
//var data = Get.arguments;
return Scaffold(
appBar: customAppBar('Student Details', context),
body: ListView.separated(
itemBuilder: (context, index) {
final record = controller.currentRecord[index];
final student = controller.students
.where(
(value) => value.documentReference!.id == record.studentId)
.toList();
return Column(
children: student.map((e) {
if (student.isEmpty) {
Get.snackbar('Error', 'No Data to show');
}
return Column(
children: [
GFListTile(
titleText: e.studentId,
),
GFListTile(
titleText: '${controller.currentRecord[index].studentId}',
),
],
);
}).toList(),
);
},
itemCount: controller.currentRecord.length,
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
));
}.
I am also adding my firebase const file that I have used for the whole application.
class FirestoreConstants {
static const pathUserCollection = "users";
static const pathStudentCollection = "student";
static const pathCurrentRDCollection = "currentRecord";
static const name = "name";
static const uid = "uid";
static const phone = "phone";
static const email = "email";
static const studentName = "studentName";
static const fatherName = " fatherName";
static const surname = "surname";
static const studentClass = "studentClass";
static const classDivision = "classDivision";
static const itsNumber = "itsNumber";
static const mobileNumber = "mobileNumber";
static const createdOn = "createdOn";
static const createdBy = "createdBy";
static const createdById = "createdById";
static const studentId = "studentId";
static const currentJuz = "currentJuz";
static const currentAyat = "currentAyat";
static const currentSurah = "currentSurah";
}
The issue is the screen is blank and it is not displaying any error no any data. Please help me out with the issue to solve. I request you to give me a working code. Thanks.
.
So I solved my own problem for now. But I am not sure it is the right way to do it.
Step 1: Change the function for getting the record to QuerySnapshot using stream and pass an id variable.
Stream<QuerySnapshot> getRecords(String id) {
return _firestore
.collection(FirestoreConstants.pathUserCollection)
.doc(_firebaseAuth.currentUser!.uid)
.collection(FirestoreConstants.pathCurrentRDCollection)
.where(FirestoreConstants.studentId, isEqualTo: id)
.snapshots();
}
I am passing an argument when going to the next screen with studentId that I am getting from index when list item is clicked.
onTap: (){
Map<String, dynamic> data() => {
FirestoreConstants.studentId:
controller.students[index].studentId,
FirestoreConstants.studentName:
controller.students[index].studentName!,
FirestoreConstants.fatherName:
controller.students[index].fatherName!,};
Get.toNamed(Routes.studentDetails, arguments: data());
}
student details screen looks like this using a stream builder to get compare id and get data from firestore.
class StudentDetails extends GetView<ViewStudentController> {
const StudentDetails({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
var data = Get.arguments;
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
stream: controller.getRecords(data[FirestoreConstants.studentId]),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text('Loading');
}
return ListView(
shrinkWrap: true,
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data[FirestoreConstants.studentId]),
subtitle: Text(data[FirestoreConstants.currentJuz]),
);
})
.toList()
.cast(),
);
},
));
}
}
I have implemented in my flutter application Authentication via Firebase by login and password.
I also connected to a Firestore table with user data.
I only need to show the authenticated user's data by their ID, which are assigned to the other data tables.
How to link e.g. Users id: 1 with Tasks User id:1 ?
home_page.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:loginui/read_data/get_user_name.dart';
class MyTaskPage extends StatefulWidget {
const MyTaskPage({Key? key}) : super(key: key);
#override
State<MyTaskPage> createState() => _MyTaskPageState();
}
class _MyTaskPageState extends State<MyTaskPage> {
final user = FirebaseAuth.instance.currentUser!;
// document IDs
List<String> docIDs = [];
// get docIDs
Future getDocId() async {
await FirebaseFirestore.instance
.collection('tasks')
.orderBy('name', descending: true)
// .where('age', isGreaterThan: 44)
.get()
.then((snapshot) => snapshot.docs.forEach((document) {
print(document.reference);
docIDs.add(document.id);
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple[200],
centerTitle: true,
actions: [
GestureDetector(
onTap: () {
setState(() {
FirebaseAuth.instance.signOut();
});
},
child: Icon(Icons.logout),
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: FutureBuilder(
future: getDocId(),
builder: (context, snapshot) {
return ListView.builder(
itemCount: docIDs.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
title: GetUserName(documentId: docIDs[index]),
tileColor: Colors.grey[200],
),
);
},
);
},
),
),
],
),
),
);
}
}
get_user_name.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName({required this.documentId});
#override
Widget build(BuildContext context) {
// get the collection
CollectionReference users = FirebaseFirestore.instance.collection('tasks');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text(
'${data['name']}',
overflow: TextOverflow.ellipsis,
softWrap: true,
);
}
return Text('Loading...');
}),
);
}
}
final _auth = FirebaseAuth.instance;
final _firestore = FirebaseFirestore.instance;
if (_auth.currentUser != null) {
// user is signed in
final uid = _auth.currentUser!.uid;
final userData = await _firestore.collection('users').doc(uid).get();
final taskData = await _firestore.collection('tasks').doc(uid).get();
// handle the data
}