How to add a DataRow in Flutter?

585

The following example code shows how you could add to or remove columns from a DataTable:

class InteractiveDataTable extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => InteractiveDataTableState();
}

class InteractiveDataTableState extends State<InteractiveDataTable> {
  final List<Map<String, String>> _data = [
    {'Country': 'China', 'Population': '1400'},
    {'Country': 'India', 'Population': '1360'},
  ];
  late List<String> _columnNames;

  void _addColumn(String newColumn) {
    if (_columnNames.contains(newColumn)) {
      return;
    }
    setState(() {
      for (var i = 0; i <= _data.length - 1; i++) {
        _data[i][newColumn] = '';
      }
      _columnNames.add(newColumn);
    });
  }

  void _removeColumn(String oldColumn) {
    if (_columnNames.length == 1 || !_columnNames.contains(oldColumn)) {
      return;
    }
    setState(() {
      for (var i = 0; i <= _data.length - 1; i++) {
        _data[i].remove(oldColumn);
      }
      _columnNames.remove(oldColumn);
    });
  }

  void _addRow(Map<String, String> newRow) {
    _columnNames.forEach((colName) {
      if (!newRow.containsKey(colName)) {
        newRow[colName] = '';
      }
    });

    setState(() {
      _data.add(newRow);
    });
  }

  @override
  void initState() {
    _columnNames = _data[0].keys.toList();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          ElevatedButton(
            onPressed: () => _addRow(
              {'Country': 'USA', 'Population': '330'},
            ),
            child: const Text('Add row'),
          ),
          SizedBox(
            height: 10,
          ),
          ElevatedButton(
            onPressed: () => _addColumn('GDP'),
            child: const Text('Add column'),
          ),
          SizedBox(
            height: 10,
          ),
          ElevatedButton(
            onPressed: () => _removeColumn('GDP'),
            child: const Text('Remove column'),
          ),
          DataTable(
            columns: _columnNames.map((columnName) {
              return DataColumn(
                label: Text(
                  columnName,
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              );
            }).toList(),
            rows: _data.map((row) {
              return DataRow(
                  cells: row.values.map((cellValue) {
                return DataCell(
                  Text(
                    cellValue,
                    style: TextStyle(
                      color: Colors.white,
                    ),
                  ),
                );
              }).toList());
            }).toList(),
          ),
        ],
      ),
    );
  }
}

If you plan to add more than a dozen rows to your DataTable, you might encounter performance issues. In such cases, the Flutter team recommends to use the PaginatedDataTable instead. From the docs:

Displaying data in a table is expensive, because to lay out the table all the data must be measured twice, once to negotiate the dimensions to use for each column, and once to actually lay out the table given the results of the negotiation. For this reason, if you have a lot of data (say, more than a dozen rows with a dozen columns, though the precise limits depend on the target device), it is suggested that you use a PaginatedDataTable which automatically splits the data into multiple pages.

Share:
585
Dalon
Author by

Dalon

Updated on December 30, 2022

Comments

  • Dalon
    Dalon about 1 year

    I have a DataTable where the user can add rows and columns. The Problem is, that when he add a new column the rows he can add in future need an extra DataCell so that columns and rows still have the same size. How can I automatically create a DataRow with matching DataCells? So far the function to add Rows is static and when the size of columns change there is an error when i try to add a new Row.

      List<DataColumn> _columnList = [
        DataColumn(label: Text('Datum', style: TextStyle(fontSize: 16))),
        DataColumn(label: ExerciseName(key: GlobalKey())),
        DataColumn(label: ExerciseName(key: GlobalKey())),
        DataColumn(label: Text('Notes', style: TextStyle(fontSize: 16), key: GlobalKey())),
      ];
    
      List<DataRow> _rowList = [
        DataRow(cells: <DataCell>[
          DataCell(Datum(key: GlobalKey())),
          DataCell(ExerciseWidget(key: GlobalKey())),
          DataCell(ExerciseWidget(key: GlobalKey())),
          DataCell(Notes(key: GlobalKey())),
        ]),
      ];
    
    
    void _addRow() {
    
          _rowList.insert(0,
              DataRow(cells: <DataCell>[
                DataCell(Datum(key: GlobalKey())),
                DataCell(ExerciseWidget(key: GlobalKey())),
                DataCell(ExerciseWidget(key: GlobalKey())),
                DataCell(Notes(key: GlobalKey())),
              ]));
          setState(() {});
      }