我需要在Firestore with Flutter中更新一个包含嵌套数组的文档。
因此,我需要将整个文档放入Map中,对“sections”数组中的Map重新排序,然后将数据存储回文档中。
但是,我不熟悉如何将快照(DocumentSnapshot)的数据导入Map。
下面的一个例子,不工作的我试图实现:
final Map<String, dynamic> doc = snapshot.data as Map<String, dynamic>;
“snapshot.data“包含文档的值。文档的结构如下所示:
{
name: "Course 1"
sections: [
{name: "Section 1"},
{name: "Section 2"}
]
}
一旦sections数组中的Map被重新排序,我需要将数据保存回文档中。
- 问题1:如何将www.example.com的内容snapshot.data读入Map?
- 问题2:我是要删除文档,然后再添加它?还是只更新所有内容?
这里是完整的函数。相关代码在“onDragFinish”中。
// Build editable list with draggable list tiles and swipe to delete
List<Widget> buildListViewEdit() {
final course = db.collection("school").document("3kRHuyk20UggHwm4wrUI")
.collection("course").document("74UsE9x7Bsgnjz8zKozv").snapshots();
return [
StreamBuilder(
stream: course,
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text("Loading...");
return Expanded(
child: DragAndDropList(
snapshot.data["sections"].length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(snapshot.data["sections"][index]["name"]),
onTap: () {
print("hello");
}
)
);
},
onDragFinish: (before, after) {
print('on drag finish $before $after');
//final docString = snapshot.data.toString();
final Map <String, dynamic> doc = snapshot.data;
//final tempSections = List.castFrom(snapshot.data["sections"]).toList();
//Map data = tempSections[before];
//tempSections.removeAt(before);
//tempSections.insert(after,data);
//snapshot.data["sections"] = tempSections;
//db.collection("school").document("3kRHuyk20UggHwm4wrUI")
//.collection("course").document("74UsE9x7Bsgnjz8zKozv").updateData(snapshot.data);
//var line = snapshot.data["sections"][before];
//snapshot.data["sections"].removeAt(before);
//snapshot.data["sections"].insert(after,line);
/*
List<Map> sections = docCopy["sections"];
Map data = docCopy["sections"][before];
sections.removeAt(before);
sections.insert(after, data);
print(sections);
*/
},
canDrag: (index) {
print('can drag $index');
return index != 3;
},
canBeDraggedTo: (one, two) => true,
dragElevation: 8.0,
)
);
}
)
];
}
尝试将www.example.com复制snapshot.data到另一个变量时出错:
flutter: ══╡ EXCEPTION CAUGHT BY GESTURE LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown while routing a pointer event:
flutter: type 'DocumentSnapshot' is not a subtype of type 'Map<String, dynamic>'
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter: https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 _SectionScreenState.buildListViewEdit.<anonymous closure>.<anonymous closure> (package:teach_mob/screens/section_screen.dart:150:45)
工作示例
感谢大家的帮助。这里有一个完整的例子,对我来说:
// Build editable list with draggable list tiles and swipe to delete
List<Widget> buildListViewEdit() {
final course = db.collection("school").document("3kRHuyk20UggHwm4wrUI")
.collection("course").document("74UsE9x7Bsgnjz8zKozv").snapshots();
return [
StreamBuilder(
stream: course,
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text("Loading...");
return Expanded(
child: DragAndDropList(
snapshot.data["sections"].length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(snapshot.data["sections"][index]["name"]),
onTap: () {
print("hello");
}
)
);
},
onDragFinish: (before, after) {
print('on drag finish $before $after');
// Convert AsyncSnapshot to DocumentSnapshot and then
// create a map that can be changed and updated.
final Map <String, dynamic> doc = snapshot.data.data;
// Convert fixed length list to dynamic list, because items in
// fixed length lists can't be added / removed.
final tempSections = List.castFrom(doc["sections"]).toList();
// Get the data of the list item to be dragged
// Remove the data from the current position
// Add the data to the new position of the list
Map data = tempSections[before];
tempSections.removeAt(before);
tempSections.insert(after,data);
// Overwrite sections with new list array
doc["sections"] = tempSections;
// Store the data back into the firestore document
db.collection("school")
.document("3kRHuyk20UggHwm4wrUI")
.collection("course")
.document("74UsE9x7Bsgnjz8zKozv")
.updateData(doc);
},
canDrag: (index) {
print('can drag $index');
return index != 3;
},
canBeDraggedTo: (one, two) => true,
dragElevation: 8.0,
)
);
}
)
];
}
8条答案
按热度按时间imzjd6km1#
根据我们的讨论,快照不是
DocumentSnapshot
,而是AsyncSnapshot
要获取文档快照,请使用
snapshot.data
要获得实际的Map,可以使用
snapshot.data.data()
它将返回您要查找的Map〈String,dynamic〉。
sf6xfgos2#
2021年5月更新
请参阅移转至cloud_firestore 2.0.0 here。
创建变量时必须定义类型:
2vuwiymt3#
为了示例
需要简化
结果
bihw5rsg4#
看起来可能是因为你有一个流构建器,所以快照是一个**
AsyncSnapshot<dynamic>
,当你获取它的.data时,你会得到一个动态**,它会返回一个DocumentSnapshot,* 然后你需要调用这个对象 * 上的.data来获取正确的**Map<String, dynamic> data
**。第一次
你也可以使用内置函数追加到数组中,但是看起来你想做一些疯狂的排序,所以一切都很好。
kulphzqa5#
2020年9月更新
要从快照文档中获取数据,现在必须调用
snapshot.data()
(cloud_firestore0.14.0 or higher
)gk7wooem6#
要从文档快照获取**Map,**请使用
snapshot.data.data
umuewwlo7#
我认为你们都错了。
从Firestore数据库获取Map字段的唯一方法是使用代码
docs.get("MapVariableName") as Map<String, dynamic>
,如下面的示例代码所示:smdncfj38#
根据以上答案,您可以尝试以下方法