title: Convert Firestore DocumentSnapshot to Map in Flutter
body: <p>I need to update a document with nested arrays in Firestore with Flutter.</p>
  
  <p>So I need to get the full document into a Map, reorder the maps in the "sections" array, and then store the data back into the document.</p>
  
  <p>I'm however unfamiliar how I can get the data of the snapshot (DocumentSnapshot) into a Map.</p>
  
  <p>Below an example that doesn't work of what I try to achieve:</p>
  
  <pre><code>final Map&lt;String, dynamic&gt; doc = snapshot.data as Map&lt;String, dynamic&gt;;
  </code></pre>
  
  <p>"snapshot.data" contains the values of the document. The structure of the document looks like this:</p>
  
  <pre><code>{
    name: "Course 1"
    sections: [
      {name: "Section 1"},
      {name: "Section 2"}
    ]
  }
  </code></pre>
  
  <p>Once the Maps in the sections array have been re-ordered, I need to save the data back into the document.</p>
  
  <ul>
  <li>Question 1: How can I read the contents of snapshot.data into a Map?</li>
  <li>Question 2: Would I delete the document, and add it again? Or can I just update all the contents?</li>
  </ul>
  
  <p>Here the full function. Relevant code is in "onDragFinish".</p>
  
  <pre><code> // Build editable list with draggable list tiles and swipe to delete
    List&lt;Widget&gt; 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 &lt;String, dynamic&gt; 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&lt;Map&gt; 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) =&gt; true,
                dragElevation: 8.0,
              )
            );
          }
        )
      ];   
    }
  </code></pre>
  
  <p>Error when trying to copy snapshot.data into another variable:</p>
  
  <pre><code>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&lt;String, dynamic&gt;'
  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.&lt;anonymous closure&gt;.&lt;anonymous closure&gt; (package:teach_mob/screens/section_screen.dart:150:45)
  </code></pre>
  
  <p><strong>Working example</strong></p>
  
  <p>Thanks all for your assistance. Here a full example that worked for me:</p>
  
  <pre><code>  // Build editable list with draggable list tiles and swipe to delete
    List&lt;Widget&gt; 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 &lt;String, dynamic&gt; 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) =&gt; true,
                dragElevation: 8.0,
              )
            );
          }
        )
      ];   
    }
  </code></pre>