Reputation: 135
I am new to Flutter as well as Android, currently I am doing Search Data from Firestore. I was able to get the data but I couldn't display it on the screen. I'm getting this error
"The method '[]' can't be unconditionally invoked because the receiver can be 'null'."
_querySnapshot.docs[index].data()['name']
And this is the code I'm using for searching
late QuerySnapshot _querySnapshot;
@override
Widget build(BuildContext context) {
Widget searchedData() {
return ListView.builder(
itemCount: _querySnapshot.docs.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
_querySnapshot.docs[index].data()['name'],
//
),
);
});
}
return LayOut(
Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.clear), onPressed: emptyTextSearch),
appBar: AppBar(
actions: [
GetBuilder<DataController>(
init: DataController(),
builder: (val) {
return IconButton(
icon: Icon(Icons.search),
onPressed: () {
val.queryData(_searchController.text).then((value) {
_querySnapshot = value;
setState(() {
isExcecuted = true;
});
});
});
})
],
title: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: 'Search', hintStyle: TextStyle(color: Colors.white)),
controller: _searchController,
),
backgroundColor: Colors.black,
),
body: isExcecuted
? searchedData()
: Container(
child: Center(
child: Text(
'Search any',
style: TextStyle(color: Colors.white, fontSize: 30.0),
),
),
),
),
);
}
DataController
class DataController extends GetxController {
Future getData(String collection) async {
final FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
QuerySnapshot snapshot =
await firebaseFirestore.collection(collection).get();
return snapshot.docs;
}
Future queryData(String queryString) async {
return FirebaseFirestore.instance
.collection('reports')
.where('property', isGreaterThanOrEqualTo: queryString)
.get();
}
}
Please help me get past this error.
Upvotes: 1
Views: 91
Reputation: 2835
@Frank's answer should work.
But you can also try this:
Map<String, dynamic> searchData = _querySnapshot.docs[index].data();
return ListTile(
title: Text(
searchData['name'],
),
);
or
List<Map<String, dynamic>> searchData = _querySnapshot.docs
.map((e) => e.data()).toList();
print(searchData);
return ListView.builder(
itemCount: searchData.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
searchData[index]['name'],
),
);
});
Also, update your code to use stricter types:
late QuerySnapshot<Map<String, dynamic>> _querySnapshot;
...
Future<QuerySnapshot<Map<String, dynamic>>> queryData(String queryString) async {
return await FirebaseFirestore.instance
.collection('reports')
.where('property', isGreaterThanOrEqualTo: queryString)
.get();
}
Upvotes: 1
Reputation: 599876
You're using version 2.0 (or later) of the FlutterFire plugin for Firestore, which requires that you specify the type of a query/snapshot. According to the documentation on migrating to cloud_firestore 2.0.
The shortest I can think of is:
(_querySnapshot.docs[index].data() as Map<String, dynamic>)['name']
But if that doesn't work you might need to modify the type of the val.queryData
that you use her:
val.queryData(_searchController.text).then((value) {
Your queryData
returns a Query
now and that needs to be a Query<Map<String, dynamic>>
. By changing that the value in then
becomes a DocumentSnapshot<Map<String, dynamic>>
, so that finally (_querySnapshot.docs[index].data()
becomes a Map<String, dynamic>
, which is what you need.
Upvotes: 2