LuCkY
LuCkY

Reputation: 33

Display firestore data with flutter in a DataTable

I was trying the Firebase for Flutter example app from Flutter's official documentation and changed the "ListTile" widget with "DataTable" and now the DataTable is printing a separate Datacolumn for every DataRow. ‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎ please view the current Output screenshot and Database la‎‎‎‎‎‎‎‎‎‎‎yout.‎‎‎ ‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/material.dart';

    void main() => runApp(MyApp());

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Baby Names',
          home: MyHomePage(),
        );
      }
    }

    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() {
        return _MyHomePageState();
      }
    }

    class Record {
      final String name;
      final String rName;
      final int votes;
      final DocumentReference reference;

      Record.fromMap(Map<String, dynamic> map, {this.reference})
          : assert(map['name'] != null),
            assert(map['r_name'] != null),
            assert(map['votes'] != null),
            name = map['name'],
            rName = map['r_name'],
            votes = map['votes'];

      Record.fromSnapshot(DocumentSnapshot snapshot)
          : this.fromMap(snapshot.data, reference: snapshot.reference);

      @override
      String toString() => "Record<$name:$votes:$rName>";
    }

    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Baby Name Votes')),
          body: _buildBody(context),
        );
      }

      Widget _buildBody(BuildContext context) {
        return StreamBuilder<QuerySnapshot>(
          stream: Firestore.instance.collection('baby').snapshots(),
          builder: (context, snapshot) {
            if (!snapshot.hasData) return LinearProgressIndicator();

            return _buildList(context, snapshot.data.documents);
          },
        );
      }

      Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
        return ListView(
          padding: const EdgeInsets.only(top: 20.0),
          children: snapshot.map((data) => _buildListItem(context, data)).toList(),
        );
      }

      Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
        final record = Record.fromSnapshot(data);

        return Padding(
          key: ValueKey(record.name),
          padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
          child: Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.grey),
              borderRadius: BorderRadius.circular(5.0),
            ),
            child: DataTable(
              columns: [
                DataColumn(label: Text('Name')),
                DataColumn(label: Text('Votes')),
                DataColumn(label: Text('Rapper\nname')),
              ],
              rows: [
                DataRow(cells: [
                  DataCell(Text(record.name)),
                  DataCell(Text(record.votes.toString())),
                  DataCell(Text(record.rName)),
                ])
              ],
            ),
          ),
        );
      }
    }

Upvotes: 3

Views: 8001

Answers (2)

Viren V Varasadiya
Viren V Varasadiya

Reputation: 27147

As can be seen from you code, it is clear that you are returning whole new DataTable and because of that you are getting column name every time.

You have to create Datatable in _buildBody method and just return List of DataRow From _buildListItem method.

I hope that following code work for you. i did not tested below code because of not having proper setup. add a comment if you face any issue again.

Widget _buildBody(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: Firestore.instance.collection('baby').snapshots(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) return LinearProgressIndicator();

        return DataTable(
          columns: [
            DataColumn(label: Text('Name')),
            DataColumn(label: Text('Votes')),
            DataColumn(label: Text('Rapper\nname')),
          ],
          rows: _buildList(context, snapshot.data.documents)
        );
      },
    );
  }




    List<DataRow> _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
        return  snapshot.map((data) => _buildListItem(context, data)).toList();
    }



 DataRow _buildListItem(BuildContext context, DocumentSnapshot data) {
    final record = Record.fromSnapshot(data);

    return DataRow(cells: [
              DataCell(Text(record.name)),
              DataCell(Text(record.votes.toString())),
              DataCell(Text(record.rName)),
            ]);
  }

Upvotes: 8

Armando Francisco
Armando Francisco

Reputation: 23

Widget build(BuildContext context) {
    final products = Provider.of<List<Product>>(context);
    return Scaffold(
        body: Container(
          child: DataTable(
            columns: [
              DataColumn(label: Text('Id')),
              DataColumn(label: Text('Name')),
              DataColumn(label: Text('Price')),
            ],
            rows: List<DataRow>.generate(
                products.length,
                (index) => DataRow(cells: [
                      DataCell(Text(products[index].productId)),
                      DataCell(Text(products[index].name)),
                      DataCell(Text(products[index].price.toString())),
                    ])),
          ),
        ),


  Stream<List<Product>> getProducts(){
    return _db.collection('products').snapshots().map((snapshot) => snapshot.docs.map((document) => Product.fromFirestore(document.data())).toList());
  }

I use provider for my state management, hope that i can help u

Upvotes: 2

Related Questions