How to add dynamically items to the table in flutter?

Viewed 33612

Do someone know how to add dynamically more rows into the DataTable in Flutter. As you can see my code is very 'hardcoded' [line: 11-31].
There should be a way to get rid of writing more and more DataRows.

Code:

class DataTableWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DataTable(
      columns: [
        DataColumn(label: Text('Patch')),
        DataColumn(label: Text('Version')),
        DataColumn(label: Text('Ready')),
      ],
      rows: <DataRow>[
        DataRow(
          cells: <DataCell>[
            DataCell(Text('AAAAAA')),
            DataCell(Text('1')),
            DataCell(Text('Yes')),
          ],
        ),
        DataRow(
          cells: <DataCell>[
            DataCell(Text('BBBBBB')),
            DataCell(Text('2')),
            DataCell(Text('No')),
          ],
        ),
        DataRow(
          cells: <DataCell>[
            DataCell(Text('CCCCCC')),
            DataCell(Text('3')),
            DataCell(Text('Yes')),
          ],
        ),
      ],
    );
  }
}
3 Answers

You can use

listOfColumns.map(((element) => DataRow(...))).toList()

This is your code using this method.

class DataTableWidget extends StatelessWidget {
  final List<Map<String, String>> listOfColumns = [
    {"Name": "AAAAAA", "Number": "1", "State": "Yes"},
    {"Name": "BBBBBB", "Number": "2", "State": "no"},
    {"Name": "CCCCCC", "Number": "3", "State": "Yes"}
  ];
//  DataTableWidget(this.listOfColumns);     // Getting the data from outside, on initialization
  @override
  Widget build(BuildContext context) {
    return DataTable(
      columns: [
        DataColumn(label: Text('Patch')),
        DataColumn(label: Text('Version')),
        DataColumn(label: Text('Ready')),
      ],
      rows:
          listOfColumns // Loops through dataColumnText, each iteration assigning the value to element
              .map(
                ((element) => DataRow(
                      cells: <DataCell>[
                        DataCell(Text(element["Name"])), //Extracting from Map element the value
                        DataCell(Text(element["Number"])),
                        DataCell(Text(element["State"])),
                      ],
                    )),
              )
              .toList(),
    );
  }
}

You could do something like this:**

class DataTableWidget extends StatelessWidget {

      List results=[] ;
       intState((){
         super.iniState();
            this.getSale();
 })
Future<String> getData () async {

var response = await http.get(
  "$saleUrl/?format=json",

);
setState(() {
  var dataConvertedToJson = 
json.decode(utf8.decode(response.bodyBytes));
  results = dataConvertedToJson['results'];
});
 print('${results.length}');
  return "successful";
 }
  DataRow _getDataRow(result) {
    return DataRow(
      cells: <DataCell>[
        DataCell(Text(data["text1"])),
        DataCell(Text(data["text2"])),
        DataCell(Text(data["text3"])),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return DataTable(
      columns: [
        DataColumn(label: Text('Patch')),
        DataColumn(label: Text('Version')),
        DataColumn(label: Text('Ready')),
      ],
      rows: List.generate(
          results.length, (index) => _getDataRow(results[index])),
    );
  }
}

The underlying data structure, probably a list, is what you want to worry about changing. UI elements like the table just observe. The setState() function notifies the UI to take a fresh look after you've updated your list.

Here's a working example hacked from a flutter doc example. Click the button to add rows.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Add Rows',
      home: MyHomePage(title: 'Add Rows'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<DataRow> _rowList = [
    DataRow(cells: <DataCell>[
      DataCell(Text('AAAAAA')),
      DataCell(Text('1')),
      DataCell(Text('Yes')),
    ]),
  ];

  void _addRow() {
    // Built in Flutter Method.
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below.
      _rowList.add(DataRow(cells: <DataCell>[
        DataCell(Text('BBBBBB')),
        DataCell(Text('2')),
        DataCell(Text('No')),
      ]));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: DataTable(columns: [
          DataColumn(label: Text('Patch')),
          DataColumn(label: Text('Version')),
          DataColumn(label: Text('Ready')),
        ], rows: _rowList),
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: _addRow,
        label: Text('Add Row'),
        backgroundColor: Colors.green,
      ),
    );
  }
}

This builds for me with

flutter build web

then run with

flutter run -d chrome
Related