My question: How can I add checkboxes to my data table to select rows?
The checkboxes are located in the first column of the table. The name of that column has a checkbox as well that selects all rows.
The individual checkbox in the column name does work and I can select all contacts.
However, when I dynamically create checkboxes using my List<DataRow> buildContactListOfDataRows method, I notice that when I setState() using the onChanged property, the value of the checkboxes is always true. This means that I cannot select/deselect individual columns.
Visual representation:
As requested I have updated my question with a testable snipped of my code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ContactsSearchPage(),
);
}
}
class Contact {
String firstName;
String lastName;
String emailAddress;
bool selected;
Contact({
this.firstName = '',
this.lastName = '',
this.emailAddress = '',
this.selected = false,
});
}
class ContactsSearchPage extends StatefulWidget {
const ContactsSearchPage({Key? key}) : super(key: key);
@override
// ignore: library_private_types_in_public_api
_ContactsSearchPageState createState() => _ContactsSearchPageState();
}
class _ContactsSearchPageState extends State<ContactsSearchPage> {
//List to hold selected contacts
List<Contact> selectedContacts = [];
bool allContactsSelected = false;
//Initialize data table data
List<DataRow> contactRows = [];
List<Contact> rowsData = [];
List<DataColumn> contactColumns = [];
List<String> columnsData = [
"",
"First Name",
"Last Name",
"Email Address",
];
@override
Widget build(BuildContext context) {
//Fill the list of Columns
contactColumns =
buildListOfDataColumns(columnsData, Colors.white, TextAlign.center);
//Fill the list of Contacts from object
if (rowsData.isEmpty) {
for (int i = 0; i < 4; i++) {
rowsData.add(Contact(
firstName: "user$i",
lastName: "test$i",
emailAddress: "email@test$i",
));
}
contactRows =
buildContactListOfDataRows(rowsData, Colors.white, TextAlign.center);
}
return Center(
child: Column(
children: [
Text(
"Selected Contacts: ${selectedContacts.length}",
style: const TextStyle(color: Colors.black),
),
SizedBox(
width: double.infinity,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FittedBox(
fit: BoxFit.scaleDown,
child: DataTable(
// ignore: prefer_const_constructors
headingTextStyle: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
),
// ignore: prefer_const_constructors
decoration: BoxDecoration(
color: Colors.blueGrey,
),
border: TableBorder.all(
width: 1.5,
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
columns: contactColumns,
rows: contactRows),
),
),
),
],
),
);
}
List<DataRow> buildContactListOfDataRows(
List<Contact> rowsData, Color textColor, TextAlign textAlign) {
List<DataRow> dataRows = [];
for (int i = 0; i < rowsData.length; i++) {
String firstName = rowsData[i].firstName;
String lastName = rowsData[i].lastName;
String emailAddress = rowsData[i].emailAddress;
DataRow row = DataRow(
cells: [
DataCell(Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: rowsData[i].selected,
onChanged: (value) {
setState(() {
rowsData[i].selected = value == null
? false
: value == false
? false
: true;
});
if (value == true) {
selectedContacts.add(rowsData[i]);
} else {
selectedContacts.remove(rowsData[i]);
}
},
activeColor: Colors.orange,
tristate: true,
))),
DataCell(Text(
firstName,
style: TextStyle(color: textColor),
textAlign: textAlign,
)),
DataCell(Text(
lastName,
style: TextStyle(color: textColor),
textAlign: textAlign,
)),
DataCell(Text(
emailAddress,
style: TextStyle(color: textColor),
textAlign: textAlign,
)),
],
);
dataRows.add(row);
}
return dataRows;
}
List<DataColumn> buildListOfDataColumns(
List<String> columnData, Color textColor, TextAlign textAlign) {
List<DataColumn> dataColumns = [];
for (int i = 0; i < columnData.length; i++) {
String columnName = columnData[i];
DataColumn column = const DataColumn(label: Text(""));
if (columnName == "") {
column = DataColumn(
label: Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: allContactsSelected,
onChanged: (value) {
setState(() {
allContactsSelected = value == null
? false
: value == false
? false
: true;
if (selectedContacts.isNotEmpty) {
selectedContacts.clear();
}
if (allContactsSelected) {
for (var element in rowsData) {
element.selected = true;
selectedContacts.add(element);
}
} else {
for (var element in rowsData) {
element.selected = false;
}
selectedContacts.clear();
}
});
},
activeColor: Colors.orange,
tristate: true,
)));
} else {
column = DataColumn(
label: Text(
columnName,
style: TextStyle(color: textColor),
textAlign: textAlign,
),
);
}
dataColumns.add(column);
}
return dataColumns;
}
}
