[英]Flutter - Firestore - List String to be from collection field and update fire store once "Save Setting' is pressed
我有兩個問題:
1.我需要使用 email 作為選擇標准從文檔中構建一個列表字符串,所以我的查詢是
Future<List<dynamic>> getDevices() async {
var firebaseUser = FirebaseAuth.instance.currentUser?.email;
var query = await firestoreInstance
.collection(devices)
.where('email', isEqualTo: '$firebaseUser')
.get();
//This is to get the Document ID to a List String, but I actually want this List String to be a
// List String of the deviceName
List<String> _documentsIds = query.docs.map((doc) => doc.id).toList();
return _documentsIds;
}
我如何 map 將設備名稱添加到列表中? 目前我 map doc.id
2.為了構建 NumberPicker,我使用 startHour 來指示開始時間。 但是每次你 select 使用 NumberPicker 一個新的“開始時間”時,它都會導致調用未來並查詢 Firesote,你無法更新該值。 假設要等到我按“保存設置”然后更新 Firestore。 關於如何實現這一目標的任何建議?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import 'package:safe/constants.dart';
import 'package:safe/components/buttons_navigate.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:numberpicker/numberpicker.dart';
class Test2 extends StatefulWidget {
const Test2({Key? key}) : super(key: key);
static const String id = 'test_2';
@override
State<Test2> createState() => _Test2State();
}
class _Test2State extends State<Test2> {
final _auth = FirebaseAuth.instance;
User? loggedInUser;
final firestoreInstance = FirebaseFirestore.instance;
final String devices = 'devices';
bool showSpinner = false;
String? deviceName;
int startHour = 0;
String? selectedDeviceValue;
final bool checkOne = false;
Color sDeviceAlways = Colors.white54;
Color sDeviceTime = Colors.white54;
FontWeight sDeviceAlwaysW = FontWeight.normal;
FontWeight sDeviceTimeW = FontWeight.normal;
@override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser;
if (user != null) {}
;
} catch (e) {
print(e);
}
}
Future<List<dynamic>> getDevices() async {
var firebaseUser = FirebaseAuth.instance.currentUser?.email;
var query = await firestoreInstance
.collection(devices)
.where('email', isEqualTo: '$firebaseUser')
.get();
//This is to get the Document ID to a List String, but I actually want this List String to be a
// List String of the deviceName
List<String> _documentsIds = query.docs.map((doc) => doc.id).toList();
return _documentsIds;
}
Future<DocumentSnapshot<Map<String, dynamic>>> getDeviceSettings() async {
var deviceSetting = await firestoreInstance
.collection(devices)
.doc(selectedDeviceValue)
.get();
startHour = deviceSetting.data()!['startHour'];
deviceName = deviceSetting.data()!['deviceName'];
print(deviceSetting.data());
print('deviceName: $deviceName');
print('startHour: $startHour');
return deviceSetting;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: [
IconButton(
onPressed: () {
_auth.signOut();
Navigator.pop(context);
},
icon: Icon(Icons.close))
],
title: const Text('Device Selection page'),
),
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 40,
child: Text(
'SAFE',
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 380,
padding: const EdgeInsets.symmetric(horizontal: 24.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.lightBlueAccent, width: 1.0),
borderRadius: kBorderRadius),
child: DropdownButtonHideUnderline(
child: FutureBuilder<List>(
future: getDevices(),
builder: (BuildContext context,
AsyncSnapshot<List<dynamic>> snapshot) {
if (!snapshot.hasData) {
return const Text(
'Waiting Devices',
);
} else {
return DropdownButton(
borderRadius: kBorderRadius,
iconSize: 40,
elevation: 16,
hint: const Text(
'Safe Devices',
),
onChanged: (value) {
setState(() {
selectedDeviceValue = value.toString();
setState(() {
selectedDeviceValue;
getDeviceSettings();
});
});
},
value: selectedDeviceValue,
items: snapshot.data
?.map((_documentsIds) =>
DropdownMenuItem<String>(
value: _documentsIds,
child: Text(_documentsIds),
))
.toList(),
);
}
})),
)
],
),
SizedBox(
height: 5,
),
// This Future is to update startHour according to selectedDeviceValue selected
// The problem is every time you change the NumberPicker it recalls from Firesore the value of
// startHour, it is suppose to update the startHour and only store it in Firestore once you
// press 'Save Settings'
FutureBuilder(
future: getDeviceSettings(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>>
snapshot) {
if (!snapshot.hasData) {
return const Text(
'Please select a Devices',
);
} else {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Container(
width: 180,
decoration: BoxDecoration(
border: Border.all(
color: Colors.lightBlueAccent,
width: 1.0),
borderRadius: kBorderRadius),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.fromLTRB(
5, 10, 5, 1),
child: const Text(
'Start Time',
),
),
Container(
padding: const EdgeInsets.fromLTRB(
1, 1, 25, 1),
child: NumberPicker(
value: startHour,
minValue: 0,
maxValue: 24,
onChanged: (value) => setState(
() => startHour = value),
),
)
],
),
)
],
)
],
),
],
);
}
}),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Buttons_Navigate(
colour: Colors.teal,
title: 'Save Settings',
onPressed: () {},
width: 200,
),
],
),
],
)),
));
}
}
對於第一個問題,我認為您可以使用List<String> devicesNames = query.docs.map((doc['deviceName']) => deviceName).toList();
讓我知道這個是否奏效
對於第二個問題,我真的沒有得到你想要什么,你能解釋一下嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.