mark
mark

Reputation: 1295

Fix top Row in Data table in flutter

I have a data table that scrolls horizontally and vertically due to the amount of data available. I want the top row which specifies the column names to always be visible when scrolling down.

code: No issues in the code I am getting the results, but when I scroll down The header wont be shown. Can any one help me in how to fix the header(1st row).

My header(1st row) elements keeps changing for each req, the way its implemented is there will be cards in my dashboard onclicking each card it hits the API and I am displaying its result i.e contents of field named header list as my first row.

Content of the header keeps changing for each card. so once any card is clicked new page containing its data will popup, there I need to fix the header.

Widget getTable(BuildContext context, var data) {
    Widget _widget;
    _widget = SingleChildScrollView(
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: DataTable(
          rows: createDataRows(context, data),
          columns: createDataColumns(context, data),
        ),
      ),
    );
    return _widget;
  }

  List<DataRow> createDataRows(BuildContext context, var jsonData) {
    List<DataRow> _dataRows = [];
    List<DataCell> _cells = [];
    String _dataCellTitle;

    Map<String, Object> headers = jsonData['headers'];
    Map<int, String> headerMapping;
    headerMapping = headers.keys
        .toList()
        .asMap()
        .map((index, value) => MapEntry(index + 1, value));

    if (jsonData["data"] == null) {
      _dataRows = [];
    } else {
      for (var j = 0; j < jsonData["data"].length; j++) {
        _cells.add(DataCell(Text('${j + 1}')));
        for (int i = 1; i <= headerMapping.length; i++) {
          _dataCellTitle = "${jsonData["data"][j][headerMapping[i]]}" ?? '-';
          _cells.add(DataCell(Text('$_dataCellTitle')));
        }
        _dataRows.add(DataRow(cells: _cells));
        _cells = [];
      }
    }
    return _dataRows;
  }

  List<DataColumn> createDataColumns(BuildContext context, var jsonData) {
    String columnTitle;
    List<DataColumn> _dataColumns = [];
    Map<String, Object> headers = jsonData['headers'];
    Map<int, String> headerMapping;
    headerMapping = headers.keys
        .toList()
        .asMap()
        .map((index, value) => MapEntry(index + 1, value));
    _dataColumns.add(DataColumn(label: Text('S. No.')));
    for (int i = 1; i <= headerMapping.length; i++) {
      columnTitle = headers[headerMapping[i]];
      _dataColumns.add(
        DataColumn(label: Text('$columnTitle')),
      );
    }
    return _dataColumns;
  }

like this here

where the first row is constant and first column also.

Upvotes: 5

Views: 8563

Answers (4)

Kushi
Kushi

Reputation: 11

This is the solution to make Datatable Header sticky :

              SizedBox(
                height: 500,
                width: 1000,
                child: Scrollbar(
                  controller: _vertical,
                  thumbVisibility: true,
                  trackVisibility: true,
                  child: Scrollbar(
                    controller: _horizontal,
                    thumbVisibility: true,
                    trackVisibility: true,
                    child: SingleChildScrollView(
                      controller: _horizontal,
                      scrollDirection: Axis.horizontal,
                      child: Stack(
                        children: [
                          SingleChildScrollView(
                            controller: _vertical,
                            scrollDirection: Axis.vertical,
                            child: DataTable(
                              rows: list_rows, // PROVIDE ROWS HERE
                              columns: List.generate(
                                list_column.length,
                                (index) => DataColumn(
                                  label: Text(''),
                                ),
                              ), //GENERATE EMPTY COLUMNS
                              headingRowHeight: 90, // HEADER HEIGHT
                            ),
                          ),
                          DataTable(
                            rows: [], // DONT PROVIDE ROWS
                            columns:
                                list_column, // PROVIDE YOUR COLUMNS HERE
                            headingRowHeight: 90, // HEADER HEIGHT
                            headingRowColor: MaterialStateColor.resolveWith(
                              (states) => Color.fromRGBO(86, 153, 255, 1),
                            ),
                            border: TableBorder.all(
                                width: 1.0, color: Colors.white),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),

Upvotes: 1

Taosif7
Taosif7

Reputation: 353

You can do the smart thing here, You can create two datatables one with only column, and one with rows.

Suppose your list_rows is a List<DataRow> and list_column is List<DataColumn> of your actual columns, then:

Column(
      children: [
        DataTable(
          rows: [], // DONT PROVIDE ROWS
          columns: list_column, // PROVIDE YOUR COLUMNS HERE
        ),
        Expanded(
          child: SingleChildScrollView(
            child: DataTable(
                rows: list_lows, // PROVIDE ROWS HERE
                columns: List.generate(
                    list_column.length, (index) => DataColumn(label: Text(''))), // GENERATE EMPTY COLUMNS
                headingRowHeight: 0, // SHRINK THE HEADER
              ),
          ),
        ),
      ],
    )

This way your columns will always be on top!

Upvotes: 1

Tasnuva Tavasum oshin
Tasnuva Tavasum oshin

Reputation: 4750

I have Used Like that , and its working fine :

SingleChildScrollView dataBody() {
        return SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: SingleChildScrollView(
              scrollDirection: Axis.vertical,
              child: DataTable(
                columnSpacing: 10,
                //sortAscending: sort,
                //sortColumnIndex: 0,
                columns: [
                  DataColumn(label: Text("Date"), numeric: false),
                  DataColumn(label: Text("Particulars"), numeric: false),
                  DataColumn(label: Text("Amount"), numeric: true)
                ],
                rows: transactions
                    .map((txn) => DataRow(cells: [
                          DataCell(
                            Text(
                              DateFormat('dd-MMM-yyyy').format(txn.date),
                              style: TextStyle(fontSize: 12.0),
                            ),
                            /*onTap: () {
                          print('Selected ${txn.date}');
                        }*/
                          ),
                          DataCell(FittedBox(
                            child: Text(
                              txn.particulars,
                            ),
                          )),
                          DataCell(Text(txn.amount.toString()))
                        ]))
                    .toList(),
              ),
            ));
      }

Upvotes: 0

Devarsh Ranpara
Devarsh Ranpara

Reputation: 1112

Okay so you have one method getTable to get data content, In it you are calling two methods

1) To fetch rows

2) To fetch columns.

But you didn't show the code of DataTable Widget.

I assume it is ListView or Column.

So in your DataTable Widget you should create one static Row for that heading.

ListView(
      children: <Widget>[
        Row(
          children: <Widget>[
            Text('$heading1'),
            Text('$heading2'),
            Text('$heading3'),
          ],
        ),

        /// Your row and column

      ],
    );

With information you provided i assume it will help you out.

Upvotes: 0

Related Questions