Reputation: 536
I am having serious difficulty in sorting columns in my DataTable.
Here is my code
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
sortColumnIndex: 0,
sortAscending: true,
columnSpacing: 5.0,
horizontalMargin: 10,
columns: [
DataColumn(label: Text('Col1'),
DataColumn(label: Text('Col2'),numeric: false ),
DataColumn(label: Text('Col3'),numeric: true ),
DataColumn(label: Text('Col4'), numeric: true),
DataColumn(label: Text('Col5'), numeric: true),
],
rows: myList
.map(
((element) => DataRow(
cells: <DataCell>[
DataCell(Text(element["Col1"]), placeholder: true,showEditIcon: false),
DataCell(Text(element["Col2"].toString())),
DataCell(Text(element["Col3"].toString())),
DataCell(Text(element["Col4"].toString())),
DataCell(Text(element["Col5"].toString())),
],
)),
).toList(),
),
));
What more am I meant to do? Ideally, I'd like to have the sort function on whichever column the user presses on, but for now, I'd be delighted with just 1 column working being sortable.
As you can see, I have added the constraints:
sortColumnIndex: 0,
sortAscending: true,
But all I get is an arrow near 1st column (ColumnIndex = 0) - which really does nothing when you press it.
What am I doing wrong?
Upvotes: 5
Views: 7327
Reputation: 19270
build(BuildContext context)
method, we should add setState(() {}
method inside the onSort: (columnIndex, ascending) {}
like below DataColumn(
label: const Text(
'Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
onSort: (columnIndex, ascending) {
print("columnIndex:$columnIndex");
print("ascending:$ascending");
setState(() {
sortColumnIndex = columnIndex;
isAscending = ascending;
});
onSort: (columnIndex, ascending) {}
will be called every time the column header is clicked.
DataTable should have state variable e.g. sortColumnIndex
, so that every sorting click on different column will reset this index, and corresponding index column will get arrow Icon.
child: DataTable(
border: TableBorder.symmetric(),
sortAscending: isAscending,
sortColumnIndex: sortColumnIndex,
isAscending will be used to revert the arrow, if the same column pressed again.
Similar to sortColumnIndex state variable; we have to sort the table data manually so that new sorted values will be rendered after the click.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
var isAscending = true;
var sortColumnIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: DataTable(
border: TableBorder.symmetric(),
sortAscending: isAscending,
sortColumnIndex: sortColumnIndex,
columns: <DataColumn>[
DataColumn(
label: const Text(
'Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
onSort: (columnIndex, ascending) {
print("columnIndex:$columnIndex");
print("ascending:$ascending");
setState(() {
sortColumnIndex = columnIndex;
isAscending = ascending;
});
},
),
DataColumn(
label: const Text(
'Age',
style: TextStyle(fontStyle: FontStyle.italic),
),
onSort: (columnIndex, ascending) {
print("columnIndex:$columnIndex");
print("ascending:$ascending");
setState(() {
sortColumnIndex = columnIndex;
isAscending = ascending;
});
},
),
DataColumn(
label: const Text(
'Role',
style: TextStyle(fontStyle: FontStyle.italic),
),
onSort: (columnIndex, ascending) {
print("columnIndex:$columnIndex");
print("ascending:$ascending");
setState(() {
sortColumnIndex = columnIndex;
isAscending = ascending;
});
},
),
],
rows: const <DataRow>[
DataRow(
cells: <DataCell>[
DataCell(Text('Sarah')),
DataCell(Text('19')),
DataCell(Text('Student')),
],
),
DataRow(
cells: <DataCell>[
DataCell(Text('Janine')),
DataCell(Text('43')),
DataCell(Text('Professor')),
],
),
DataRow(
cells: <DataCell>[
DataCell(Text('William')),
DataCell(Text('27')),
DataCell(Text('Associate Professor')),
],
),
],
),
),
);
}
}
Upvotes: 2
Reputation: 133
You have to add an onSort
property to the column that will be sorted, and call a sorting function.
bool sort = true; // or `false`...
DataTable(
sortAscending: sort,
sortColumnIndex: 0,
columns: [
DataColumn(
label: Text("Col1"),
onSort: (columnIndex, ascending) {
setState(() {
sort = !sort;
});
onSortColum(columnIndex, ascending);
}),
...
And the onSortColum
function:
onSortColum(int columnIndex, bool ascending) {
if (columnIndex == 0) {
if (ascending) {
yourDataList.sort((a, b) => a['name'].compareTo(b['name']));
} else {
yourDataList.sort((a, b) => b['name'].compareTo(a['name']));
}
}
}
Upvotes: 11