Конвертировать FireStore DocumentSnapshot в карту во флаттере - PullRequest
0 голосов
/ 23 июня 2019

Мне нужно обновить документ с вложенными массивами в Firestore с помощью Flutter.

Итак, мне нужно получить полный документ на карте, изменить порядок карт в массиве «section» и затем сохранить данные обратно в документ.

Однако я не знаю, как мне получить данные моментального снимка (DocumentSnapshot) на карту.

Ниже приведен пример, который не работает из того, чего я пытаюсь достичь:

final Map<String, dynamic> doc = snapshot.data as Map<String, dynamic>;

«snapshot.data» содержит значения документа. Структура документа выглядит следующим образом:

{
  name: "Course 1"
  sections: [
    {name: "Section 1"},
    {name: "Section 2"}
  ]
}

Как только карты в массиве разделов были переупорядочены, мне нужно сохранить данные обратно в документ.

  • Вопрос 1: Как я могу прочитать содержимое файла snapshot.data на карту?
  • Вопрос 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,
            )
          );
        }
      )
    ];   
  }

Ошибка при попытке скопировать 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,
            )
          );
        }
      )
    ];   
  }

Ответы [ 3 ]

1 голос
/ 24 июня 2019

Согласно нашему обсуждению снимок не является DocumentSnapshot, это AsyncSnapshot

, чтобы получить DocumentSnaphot, используйте snapshot.data

, чтобы получить действительную карту, которую вы можете использовать snapshot.data.data

1 голос
/ 24 июня 2019

Необходим для упрощения в целях примера enter image description here

class ItemsList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // get the course document using a stream
    Stream<DocumentSnapshot> courseDocStream = Firestore.instance
        .collection('Test')
        .document('4b1Pzw9MEGVxtnAO8g4w')
        .snapshots();

    return StreamBuilder<DocumentSnapshot>(
        stream: courseDocStream,
        builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {

            // get course document
            var courseDocument = snapshot.data.data;

            // get sections from the document
            var sections = courseDocument['sections'];

            // build list using names from sections
            return ListView.builder(
              itemCount: sections != null ? sections.length : 0,
              itemBuilder: (_, int index) {
                print(sections[index]['name']);
                return ListTile(title: Text(sections[index]['name']));
              },
            );
          } else {
            return Container();
          }
        });
  }
}

Результаты enter image description here

1 голос
/ 24 июня 2019

Похоже, возможно, потому что у вас есть построитель потоков, поэтому Снимок - это AsyncSnapshot<dynamic>, когда вы получаете его .data, вы получаете динамический , который возвращает DocumentSnapshot , , который затем необходимо вызвать .data для этого объекта , чтобы получить правильные Map<String, dynamic> data.

builder: (context, snapshot) {
final DocumentSnapshot  ds = snapshot.data;
final Map<String, dynamic> map = ds.data;
}

Snapshot Data Doc Data

Вы также можете добавлять массивы, используя встроенные функции, но похоже, что вы хотите сделать некоторую безумную сортировку, так что всехорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...