[英]Flutter Firebase Problems with Query Firestore and Streambuilder()
[英]flutter dynamic query Firebase Firestore
我正在創建一個視圖,用戶可以在其中 select 幾個元素。 然后通過在按鈕上執行 onTap,這應該會生成查詢並將查詢結果顯示在另一個視圖上。 我的挑戰是確保獲得用戶選擇的所有標准,然后使用多個字段值構建查詢。
我應該先做一個查詢,然后再對該查詢等進行查詢嗎? 謝謝
現在,當我在做幾個Where時,查詢返回了不應該返回的記錄。 不知道為什么。 請問,你能幫忙嗎? 非常感謝。
我附上了視圖的屏幕截圖。
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
import 'package:my_gtd_20220804/Constante/Const.dart';
import 'engage_display_result_search.dart';
//######################
List <dynamic> _statusSelected2 =[];
//######################
String? _timeSelectedPicker = '';
String? _energySelectedPicker = '';
String _importantSelectedPicker = '';
String _urgentSelectedPicker = '';
int valuePickerTimeSelected =0;
int valuePickerEnergySelected =0;
int valuePickerImportantSelected =0;
int valuePickerUrgentSelected =0;
List <MultiSelectItem<dynamic>>_allContexts=[];
List <dynamic> _contextSelected = [];
List <MultiSelectItem<dynamic>>result=[];
List<Status?> _statusSelected =[];
List<String> contextWhere=[];
List<String> importantWhere =[];
List<String> urgentWere =[];
final _multiSelectKeyContext = GlobalKey<FormFieldState>();
final _multiSelectKeyStatus = GlobalKey<FormFieldState>();
class Status {
final int id;
final String name;
Status({
required this.id,
required this.name,
});
}
class EngagePage extends StatefulWidget {
const EngagePage({ Key? key, }):super(key:key);
// final String title;
@override
_EngagePageState createState() => _EngagePageState();
}
class _EngagePageState extends State<EngagePage> {
static final List<MultiSelectItem<dynamic>> _context = [];
static final List<Status> _status = [
Status(id: 1, name: "Scheduled for"),
Status(id: 2, name: "Waiting for"),
];
final _itemsStatus = _status
.map((status) => MultiSelectItem<Status>(status, status.name))
.toList();
List <MultiSelectItem<dynamic>>allContexts=[];
@override
void initState() {
_contextSelected = _context;
_statusSelected = _status;
getAllContextInFirebaseV1().then(( List<dynamic> testallContexts) {
setState(() {
allContexts=testallContexts.map((e) => MultiSelectItem(e, e)).toList();
});
});
super.initState();
}
Future <List<dynamic>> getAllContextInFirebaseV1() async {
CollectionReference ref = FirebaseFirestore.instance.collection('Users')
.doc((FirebaseAuth.instance.currentUser!.uid))
.collection('contexts');
QuerySnapshot contextsQuery = await ref.get();
final allContexts = contextsQuery.docs.map((snap) => (snap.data() as Map<String, dynamic>)['context_Name']).toList();
return allContexts; //List<MultiSelectItem<dynamic>>;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ENGAGE'),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () async {
await BuildQueryResearch();
search();
},
child: const Icon(
Icons.search,
size: 26.0,
),
)
),
]
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
const SizedBox(height: 10),
MultiSelectBottomSheetField(
key: _multiSelectKeyContext,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Context", style: TextStyle(fontSize: 19),),
buttonText: const Text(
"Context", style: TextStyle(fontSize: 19),),
searchTextStyle: const TextStyle(fontSize: 19),
searchHintStyle: const TextStyle(fontSize: 19),
itemsTextStyle: const TextStyle(fontSize: 19),
items: allContexts,
searchable: true,
onConfirm: (valueContext) {
setState(() {
_contextSelected = valueContext;
});
_multiSelectKeyContext.currentState!.validate();
},
chipDisplay: MultiSelectChipDisplay(
textStyle: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold,fontSize: 19),
onTap: (dynamic item) {
setState(() {
});
_multiSelectKeyContext.currentState!.validate();
},
),
),
const SizedBox(height: 40),
//MultiSelect For Status
MultiSelectBottomSheetField<Status?>(
key: _multiSelectKeyStatus,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Status", style: TextStyle(fontSize: 19),),
buttonText: const Text("Status", style: TextStyle(fontSize: 19),),
searchTextStyle: const TextStyle(fontSize: 19),
searchHintStyle: const TextStyle(fontSize: 19),
itemsTextStyle: const TextStyle(fontSize: 19),
items: _itemsStatus,
searchable: true,
onConfirm: (values2) {
setState(() {
_statusSelected = values2 ;
_statusSelected2.add(values2);
});
_multiSelectKeyStatus.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
textStyle: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold,fontSize: 19),
onTap: (item) {
setState(() {
// _statusSelected.remove(item);
});
_multiSelectKeyStatus.currentState!.validate();
},
),
),
const SizedBox(height: 40),
//######### Energy & Time / Important /urgent
Card(
child:
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Time
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
if (_timeSelectedPicker!.length <
2 )...[
const Icon(Icons.timer),
const Text('Time', style: TextStyle(
color: Colors.black,))
]
else
...[
const Icon(Icons.timer),
Text(_timeSelectedPicker!,
style: const TextStyle(
color: Colors.black,))
],
]
)
),
onTap: () {
_showPickerTime(context, TimeList);
},
),
),
//Energy
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_energySelectedPicker!.length <
2 )...[
const Icon(Icons.battery_charging_full,
color: Colors.black,),
const Text('Energy', style: TextStyle(
color: Colors.black,))
]
else
...[
const Icon(Icons.battery_charging_full,
color: Colors.black,),
Text(_energySelectedPicker!,
style: const TextStyle(
color: Colors.black,))
],
],
)
),
onTap: () {
_showPickerEnergy(context, energyList);
},
),
),
//Important
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
if (_importantSelectedPicker ==
'' )...[
const Icon(Icons.star_border,
color: Colors.black,),
const Text('Important?', style: TextStyle(
color: Colors.black,))
],
if (_importantSelectedPicker ==
'Not Important' )...[
const Icon(Icons.star_border,
color: Colors.black,),
const Text('Not Important',
style: TextStyle(
color: Colors.black,))
],
if (_importantSelectedPicker ==
'All' )...[
const Icon(Icons.star_border,
color: Colors.orange,),
const Text('All', style: TextStyle(
color: Colors.black,))
],
if (_importantSelectedPicker ==
'Important' )...[
const Icon(Icons.star,
color: Colors.orange,),
const Text('Important', style: TextStyle(
color: Colors.black,))
]
]
)),
onTap: () {
_showPickerImportant(context, importantList);
},
),
),
//Urgent
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
if (_urgentSelectedPicker == '' )...[
const Icon(Icons.outlined_flag,
color: Colors.black,),
const Text('Urgent?', style: TextStyle(
color: Colors.black,))
],
if (_urgentSelectedPicker ==
'Not Urgent' )...[
const Icon(Icons.outlined_flag,
color: Colors.black,),
const Text('Not Urgent', style: TextStyle(
color: Colors.black,))
],
if (_urgentSelectedPicker ==
'All' )...[
const Icon(Icons.outlined_flag,
color: Colors.orange,),
const Text('All', style: TextStyle(
color: Colors.black,))
],
if (_urgentSelectedPicker ==
'Urgent' )...[
const Icon(Icons.flag, color: Colors.red,),
Text(_urgentSelectedPicker,
style: const TextStyle(
color: Colors.black,))
]
],
)
),
onTap: () {
_showPickerUrgent(context, urgentList);
setState(() {
});
},
),
),
],
),
)),
const SizedBox(height: 40),
Container(height: 200,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(child:
const Text('CANCEL'),
onPressed: () {
getAllContextInFirebaseV1();
// Navigator.pop(context);
}
),
ElevatedButton(child:
const Text('FIND'),
onPressed: () async {
// await BuildQueryResearch();
await search();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Engage_Display_Results(contextWhere,importantWhere,urgentWere)));
}
),
],
),
])));
}
void _showPickerImportant(BuildContext ctx, List myListImportant) {
showCupertinoModalPopup(
context: ctx,
builder: (_) =>
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: const BoxDecoration(
color: Color(0xffffffff),
border: Border(
bottom: BorderSide(
color: Color(0xff999999),
width: 0.0,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
onPressed: () {
Navigator.of(context).pop(_showPickerImportant);
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
child: const Text('Cancel'),
),
const DefaultTextStyle(
style: TextStyle(fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.bold),
child: Text('Time Needed'),
),
// Text('Energy Needed', style: TextStyle(fontSize: 12.0, color: Colors.black),
// ),
CupertinoButton(
onPressed: () {
setState(() {
// valuePickerEnergySelected = value;
_importantSelectedPicker =
importantList[valuePickerImportantSelected];
});
_importantSelectedPicker =
importantList[valuePickerImportantSelected];
Navigator.of(context).pop(_showPickerImportant);
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
child: const Text('Confirm'),
),
],
),
),
Container(
//width: 360,
height: 250,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
child: CupertinoTheme(
data: const CupertinoThemeData(
textTheme: CupertinoTextThemeData(
// dateTimePickerTextStyle: TextStyle(color: Colors.blue, fontSize: 16),
// pickerTextStyle: TextStyle(color: Colors.green, fontSize: 12
// )
)),
child: CupertinoPicker(
backgroundColor: Colors.white,
itemExtent: 30,
scrollController: FixedExtentScrollController(
initialItem: myListImportant.indexOf(
_importantSelectedPicker)),
useMagnifier: true,
magnification: 1.3,
children: [
for (String name in myListImportant) Center(
child: Text(name)),
],
onSelectedItemChanged: (value) {
setState(() {
valuePickerImportantSelected = value;
});
},
)
),
),
]
));
}
void _showPickerUrgent(BuildContext ctx, List myListUrgent) {
showCupertinoModalPopup(
context: ctx,
builder: (_) =>
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: const BoxDecoration(
color: Color(0xffffffff),
border: Border(
bottom: BorderSide(
color: Color(0xff999999),
width: 0.0,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
onPressed: () {
Navigator.of(context).pop(_showPickerTime);
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
child: const Text('Cancel'),
),
const DefaultTextStyle(
style: TextStyle(fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.bold),
child: Text('Urgent?'),
),
// Text('Energy Needed', style: TextStyle(fontSize: 12.0, color: Colors.black),
// ),
CupertinoButton(
onPressed: () {
setState(() {
// valuePickerEnergySelected = value;
_urgentSelectedPicker =
myListUrgent[valuePickerUrgentSelected];
});
_urgentSelectedPicker =
myListUrgent[valuePickerUrgentSelected];
Navigator.of(context).pop(_showPickerUrgent);
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
child: const Text('Confirm'),
),
],
),
),
Container(
//width: 360,
height: 250,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
child: CupertinoTheme(
data: const CupertinoThemeData(
textTheme: CupertinoTextThemeData(
// dateTimePickerTextStyle: TextStyle(color: Colors.blue, fontSize: 16),
// pickerTextStyle: TextStyle(color: Colors.green, fontSize: 12
// )
)),
child: CupertinoPicker(
backgroundColor: Colors.white,
itemExtent: 30,
scrollController: FixedExtentScrollController(
initialItem: urgentList.indexOf(
_urgentSelectedPicker)),
useMagnifier: true,
magnification: 1.3,
children: [
for (String name in myListUrgent) Center(
child: Text(name)),
],
onSelectedItemChanged: (value) {
setState(() {
valuePickerUrgentSelected = value;
});
},
)
),
),
]
));
}
Future <void> search() async{
if (_contextSelected.isEmpty ){
//TODO SHOW DIALOG
return;
}
else
{
}
}
}
body: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.collection('allTasks')
.where('task_Context', arrayContainsAny: whereQueryContext)
.where('Important', arrayContainsAny: whereQueryImportant)
.where('Urgent', arrayContainsAny: whereQueryUrgent)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
else {
return Container(
height: MediaQuery.of(context).size.height * .78,
width: MediaQuery.of(context).size.width,
child: ListView(
children: snapshot.data!.docs.map((document) {
return Card(
child: Text(document['task_Name']),
);
}).toList(),
),
);
}
}),
),
],
),
您需要添加盡可能多的查詢條件。
baseQuery.where('field', isEqualTo:'value') -> this is a new query
.where('field2', isEqualTo: 'value2)
.get();
因此,假設您將 String 作為鍵和值:
Query<Map<String, dynamic>> query = baseQueryFromYourCollection;
for(int i=0;i<keyAndValues.length;++i){
final YourKeyValueClass keyValue = keyAndValues[i];
final String key = keyValue.key;
final String value = keyValue.value;
query = query.where(key, isEqualsTo: value); // you need to reassign the query
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.