2
votes

Comment afficher la liste de Firestore dans un générateur d'éléments

La méthode getIngredients () ci-dessous renvoie une liste de firestore.

 Widget build(BuildContext context) {
    return Container(
      child: FutureBuilder(
          future: getIngredients(),
          builder: (context, AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data.documents.length,
                itemBuilder: (context, index) {
                  DocumentSnapshot user = snapshot.data.documents[index];

                  return SingleIngredient(
                    // Access the fields as defined in FireStore
                    ingredient_name: user.data['ingredients'][index].toString(),
                  );
                },
              );
            } else if (snapshot.connectionState == ConnectionState.done &&
                !snapshot.hasData) {
              // Handle no data
              return Center(
                child: Text("No users found."),
              );
            } else {
              // Still loading
              return CircularProgressIndicator();
            }
          }),
    );
  }
}

Maintenant, je veux afficher cette liste dans un générateur d'élément ci-dessous:

 new ListView.builder(
                  itemExtent: 90,
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                      return SingleIngredient(
                        ingredient_name: snapshot.data[index].ingredients,
                      );
                  });

Je reçois le message d'erreur suivant:

_FutureBuilderState # 7cbda): I / flutter (12164): La classe 'QuerySnapshot' n'a pas de getter d'instance 'length'. I / scintillement (12164): Récepteur: Instance de l'I / Flutter 'QuerySnapshot' (12164): Essayé appel: longueur

Voici la scturcture de mon firestore. Je vais chercher la liste des ingrédients:

 entrez la description de l'image ici

UPDATE J'ai mis à jour le code mais je ne reçois que le premier élément de la liste des ingrédients (c'est-à-dire les oignons). Je veux que l'itembuilder crée chaque élément de la liste car j'essaie d'afficher une image et la liste des ingrédients. C'est ce que fait le widget SingleIngredient. Alors, comment puis-je parcourir chaque liste une par une?

Future getIngredients() async {
    return Firestore.instance
        .collection('ingredients')
        .where("name", isEqualTo: widget.dish_name.toString().toLowerCase()).getDocuments();
  }


1 commentaires

Vous devez utiliser snapshot.data.documents pour accéder aux documents d'une requête, donc pour obtenir la longueur, ce sera snapshot.data.documents.length .


3 Réponses :


0
votes

Dart ne sait pas quel type vous renvoyez du Futur, il l'interprète donc comme un objet dynamique, qui n'a pas de capteur de longueur. Changez votre méthode

Future<List<YourType>> getIngredients() async {
return Firestore.instance
    .collection('ingredients')
    .where("name", isEqualTo: widget.dish_name.toString().toLowerCase()).getDocuments();

}

Future getIngredients() async {
return Firestore.instance
    .collection('ingredients')
    .where("name", isEqualTo: widget.dish_name.toString().toLowerCase()).getDocuments();

}

Où YourType est le type renvoyé par la fonction getDocuments (). Vous devrez peut-être également faire une toList () dessus.


4 commentaires

J'obtiens l'erreur suivante lorsque j'implémente vos modifications: Le type de retour 'Future n'est pas un' Future > 'tel que défini par la méthode getIngredients


@bangbang renvoyez-vous une List que renvoie getDocuments?


Veuillez consulter la structure du document Firestore ci-jointe. Je retourne une liste d'ingrédients (cordes).


Si je change ma requête en quelque chose comme ceci: Future getIngredients () async {return Firestore.instance .collection ('ingredients') .where ("name", isEqualTo: widget.dish_name.toString (). ToLowerCase ()). Snapshots () .listen ((data) => data.documents.forEach ((doc) => print (doc ["ingrédients"]))); } Je peux obtenir une liste d'ingrédients. Je ne sais tout simplement pas comment l'afficher dans un widget



4
votes

Voici un exemple utilisant StreamBuilder où je récupère tous les documents d'une collection et crée un ListView pour les afficher:

Scaffold(
    body: FutureBuilder(
        future:
            Firestore.instance.collection('users').getDocuments(),
        builder: buildUserList,
    )
)

Utilisation :

Scaffold(
    body: StreamBuilder(
        stream:
            Firestore.instance.collection('users').snapshots(),
        builder: buildUserList,
    )
)

ou

Widget buildUserList(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
    if (snapshot.hasData) {
        return ListView.builder(
            itemCount: snapshot.data.documents.length,
            itemBuilder: (context, index) {
                DocumentSnapshot user = snapshot.data.documents[index];

                return ListTile(
                    // Access the fields as defined in FireStore
                    title: Text(user.data['firstName']),
                    subtitle: Text(user.data['lastName']),
                );
            },
        );
    } else if (snapshot.connectionState == ConnectionState.done && !snapshot.hasData {
        // Handle no data
        return Center(
            child: Text("No users found."),
        );
    } else {
        // Still loading
        return CircularProgressIndicator();
    }
}


11 commentaires

L'exemple que vous avez fourni imprime les champs à valeur unique. Je veux imprimer et stocker un champ de tableau. Comment je fais ça?


Vous pouvez renvoyer n'importe quel widget du générateur pour afficher tout type de données que vous souhaitez. Il n'est pas nécessaire que ce soit une ListView . Tous les champs de DocumentSnapshot.data sont dynamiques donc vous pouvez simplement faire quelque chose comme List list = snapshot.data.documents [index] .data [' myListKey ']; pour récupérer la valeur.


Les deux fonctionneront réellement. Si vous souhaitez utiliser getDocuments () , vous avez besoin d'un FutureBuilder car cela renvoie un Future . Ici, appeler snapshots () le fait renvoyer un Stream


Exactement, j'utilise FututeBuilder mais comment afficher les résultats sans utiliser streambuilder? Pouvez-vous me donner un exemple d'accès à un champ de tableau de firestore?


Ils sont utilisés essentiellement de la même manière. Réponse mise à jour


Je suppose que ma question est, à l'intérieur du ListTile, si je veux obtenir la liste des ingrédients, dois-je juste faire des ingrédients: Text (user.data ['ingredients'])?


Oui, attribuez-le simplement à une liste comme ce que j'ai écrit dans le premier commentaire.


Je veux que itemCount: snapshot.data.documents.length, renvoie la longueur de la liste d'ingrédients par opposition à la longueur du document. Comment je fais ça?


Si vous êtes sûr que vous n'aurez qu'un seul document renvoyé, utilisez snapshot.data.documents.single.data ['ingredients']. Length


Et comment dois-je accéder à chaque élément? nom_ingrédient:?


continuons cette discussion dans le chat .



0
votes
body: StreamBuilder(
stream: Firestore.instance
    .collection('ups')
.where('pc',
isEqualTo: widget.post.data["pc"])
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: Text("Loading..."),
);
} else {
final ups = snapshot.data.documents;
List<String> stateWidget = [];
for (var message in ups) {
final stateText = message.data['state'];
// final stateCollection = Text('$stateText');
stateWidget.add(stateText);
}enter code here
return  ListView(
children: stateWidget
    .map((data) => ListTile(`enter code here`
title: Text(data),
onTap: () => {_selectedItem(data)}))
    .toList(),`enter code here`
)

1 commentaires

Salut @miriam, pouvez-vous indenter le code pour le rendre plus lisible. Des accolades fermantes semblent manquer et la chaîne entrez le code ici semble incorrecte.