converting documentSnapshot to a custom model with flutter and firestore

Viewed 1914

I have the code which only deals with searching words from cloud_firestore which is a firebase service. Searching is done fine and everything is working fine but i would love to convert my firebase DocumentSnapshot to a custom model. I don't wan;t it to be showing instace of 'DocumentSnapShot' of which i don't wan't. I wan't it to be showing at least instance of 'WordsSearch' when i print(data): Full search code:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:kopala_dictionary/models/words.dart';
import 'package:kopala_dictionary/screens/author/word_details.dart';
import 'package:provider/provider.dart';

class CloudFirestoreSearch extends StatefulWidget {
  @override
  _CloudFirestoreSearchState createState() => _CloudFirestoreSearchState();
}

class _CloudFirestoreSearchState extends State<CloudFirestoreSearch> {
  String name = "";

  //words list from snappshots

  List<Words> _wordsFromSnapShots(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      return Words(
        word: doc.data['word'],
        englishTranslation: doc.data['english_translation'],
        bembaTranslation: doc.data['bemba_translation'],
      );
    }).toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.arrow_back_ios),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        title: Card(
          child: TextField(
            decoration: InputDecoration(
                prefixIcon: Icon(Icons.search), hintText: 'Search...'),
            onChanged: (val) {
              setState(() {
                name = val;
              });
            },
          ),
        ),
      ),
      body: StreamBuilder<QuerySnapshot>(
        stream: (name != "" && name != null)
            ? Firestore.instance
                .collection('words')
                .where("word", isGreaterThanOrEqualTo: name)
                .snapshots()
            : Firestore.instance.collection("words").snapshots(),
        builder: (context, snapshot) {
          return (snapshot.connectionState == ConnectionState.waiting)
              ? Center(child: CircularProgressIndicator())
              : ListView.builder(
                  itemCount: snapshot.data.documents.length,
                  itemBuilder: (context, index) {
                    DocumentSnapshot data = snapshot.data.documents[index];
                    print(data);
                    return Card(
                      child: Column(
                        children: <Widget>[
                          SizedBox(
                            width: 25,
                          ),
                          ListTile(
                            onTap: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) =>
                                        WordsDetails(word: data)),
                              );
                            },
                            leading: Text(
                              data['word'],
                              style: TextStyle(
                                fontWeight: FontWeight.w700,
                                fontSize: 20,
                              ),
                            ),
                          ),
                        ],
                      ),
                    );
                  },
                );
        },
      ),
    );
  }
}

And this is a custom WordsSearch class:

class WordsSearch {
  final String word;
  final String englishTranslation;
  final String bembaTranslation;
  final DateTime date_posted;
  Words(
      {this.word,
      this.englishTranslation,
      this.bembaTranslation,
      this.date_posted});
}
1 Answers

You can do this using a .fromFirestore method in your model object.

factory Words.fromFirestore(DocumentSnapshot doc) {
    Map data = doc.data();

    // you likely need to convert the date_posted field.  something like this
    Timestamp datePostedStamp = data['date_posted'];

    var datePosted = new DateTime.fromMillisecondsSinceEpoch(datePostedStamp.millisecondsSinceEpoch);

    return Words(
        word: data['word'] ?? '',
        englishTranslation: data[''] ?? '',
        bembaTranslation: data['bembaTranslation'] ?? '',
        date_posted: datePosted
    );
}

Elsewhere...

List<Words> _wordsFromSnapShots(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      return Words.fromFirestore(doc);
    }).toList();
}

Remember to convert the date posted before sending into firebase. Here's how I've done it.

Timestamp.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch)
Related