I have a problem with DataTable in flutter. I want to change the state of the row, when the user click on one of them, but I found just how to do this "manually" with selected: true, inside DataRow.
How can I let the user select just a single row, and deselect the rest, by changing the state?
content: Column(
children: <Widget>[
DataTable(
columns: [
DataColumn(label: Text('Language')),
DataColumn(label: Text('Translation')),
],
rows: [
DataRow(selected: true, cells: [
DataCell(
Text(
"RO",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
),
onTap: () {
setState(() {
color = Colors.lightBlueAccent;
});
},
),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'paine'),
),
),
]),
DataRow(cells: [
DataCell(
Text(
"EN",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('EN is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'bread'),
),
),
]),
DataRow(cells: [
DataCell(
Text(
"FR",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('FR is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'pain'),
),
),
]),
],
),
],
),
You can copy past run full code below
You can use condition in selected like this 0 == selectedIndex where 0 is DataRow index
and change selectedIndex in onSelectChanged
code snippet
int selectedIndex = -1;
...
rows: [
DataRow(
selected: 0 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 0;
});
},
...
DataRow(
selected: 1 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 1;
});
},
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Color color;
int selectedIndex = -1;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
DataTable(
onSelectAll: (val) {
setState(() {
selectedIndex = -1;
});
},
columns: [
DataColumn(label: Text('Language')),
DataColumn(label: Text('Translation')),
],
rows: [
DataRow(
selected: 0 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 0;
});
},
cells: [
DataCell(
Text(
"RO",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
),
onTap: () {
setState(() {
color = Colors.lightBlueAccent;
});
},
),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'paine'),
),
),
]),
DataRow(
selected: 1 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 1;
});
},
cells: [
DataCell(
Text(
"EN",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('EN is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'bread'),
),
),
]),
DataRow(
selected: 2 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 2;
});
},
cells: [
DataCell(
Text(
"FR",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('FR is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'pain'),
),
),
]),
],
),
],
),
),
);
}
}
When I needed to call something when I pressed on the DataRow I did the following:
DataRow(
onSelectChanged(_) {
// do something here
}
cells: [],
),
Maybe this will help?
EDIT: this is a simple example of how to select/deselect rows
import 'package:flutter/material.dart';
class Stack1 extends StatefulWidget {
#override
_Stack1State createState() => _Stack1State();
}
class _Stack1State extends State<Stack1> {
bool row1Selected = false;
bool row2Selected = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: DataTable(
columns: [
DataColumn(
label: Text('My Data'),
),
],
rows: [
DataRow(
selected: row1Selected,
onSelectChanged: (value) {
setState(() {
row1Selected = value;
});
},
cells: [
DataCell(
Text('Data 1'),
),
],
),
DataRow(
selected: row2Selected,
onSelectChanged: (value) {
setState(() {
row2Selected = value;
});
},
cells: [
DataCell(
Text('Data 2'),
),
],
),
],
),
);
}
}
DataTable(
dataTextStyle: TextStyle(
fontSize: 12,
),
headingTextStyle: TextStyle(fontSize: 12),
dataRowHeight: 100,
decoration: BoxDecoration(
color: Constants.backgroundColor,
borderRadius: BorderRadius.circular(20),
// border: Border.all(color: Colors.black),
boxShadow: [
BoxShadow(
color: Colors.grey,
spreadRadius: 2,
blurRadius: 2,
offset: Offset(1, 1),
),
],
),
dividerThickness: 2,
showCheckboxColumn: false,
onSelectAll: (value) {},
columns: [
DataColumn(
label: Text(
'Unit No.',
style: TextStyle(
fontWeight: FontWeight.bold, color: Constants.appColor2),
)),
DataColumn(
label: Text(
'Unit Type',
style: TextStyle(
fontWeight: FontWeight.bold, color: Constants.appColor2),
)),
DataColumn(
label: Text(
'Description',
style: TextStyle(
fontWeight: FontWeight.bold, color: Constants.appColor2),
)),
],
rows: List.generate(
data.length,
(index) => DataRow(
selected: selectedUnit == index,
onSelectChanged: (value) {
print(value);
setState(() {
selectedUnit = index;
unitNumber = data[index].unitId;
});
PersistentNavBarNavigator.pushNewScreen(context,
screen: ShowProductDetails(
unitId: data[index].unitId,
));
},
cells: [
DataCell(Text(
data[index].unitId,
style: TextStyle(
color: Constants.matGold,
),
)),
DataCell(Text(
data[index].unitType,
style: TextStyle(
color: Constants.peach,
),
)),
DataCell(Text(
data[index].decription,
style: TextStyle(
color: Constants.appColor,
),
)),
]),
),
),
Related
when i navigate from NewSales screen to CreateItem screen and add item and press the add button
the item is added to sqflite database then it navigates back to new sales but the state is not updated , it's updated only if i restarted the app
the NewSales screen
class _NewSalesState extends State<NewSales> {
final controller = TextEditingController();
showAlertDialog(BuildContext context,String name) {
// Create button
// Create AlertDialog
AlertDialog alert = AlertDialog(
title: const Text("Alert"),
content: const Text("you want to delete this item?"),
actions: [
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green)),
child: const Text("CANCEL", style: TextStyle(color: Colors.white)),
onPressed: () {
Navigator.of(context).pop();
},
),
BlocBuilder<SalesCubit, SalesState>(
builder: (context, state) {
final bloc=BlocProvider.of<SalesCubit>(context);
return TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red)),
child: const Text(
"DELETE",
style: TextStyle(color: Colors.white),
),
onPressed: () {
Navigator.of(context).pop();
bloc.deleteItem(name).then((value) {
bloc.getAllItems();
});
},
);
},
)
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
// #override
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery
.of(context)
.size;
return BlocConsumer<SalesCubit, SalesState>(
listener: (context, state) {},
builder: (context, state) {
final bloc = BlocProvider.of<SalesCubit>(context);
if (state is SalesInitial) {
bloc.getAllItems();
}
return Scaffold(
drawer: const navDrawer(),
appBar: AppBar(
title: const Text("Ticket"),
actions: [
IconButton(
onPressed: () async {
String barcodeScanRes;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
barcodeScanRes = await FlutterBarcodeScanner.scanBarcode(
'#ff6666', 'Cancel', true, ScanMode.BARCODE);
print('barcodeScanRes $barcodeScanRes');
print(bloc.bsResult);
} on PlatformException {
barcodeScanRes = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
bloc.toggleSearch();
controller.text = barcodeScanRes;
bloc.filterItems(barcodeScanRes);
},
icon: const Icon(Icons.scanner),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () {
Navigator.of(context).pushNamed(Routes.addCustomerRoute);
},
icon: Icon(Icons.person_add)),
),
],
),
body: Column(
children: [
// the first button
Container(
width: double.infinity,
height: deviceSize.height * .1,
color: Colors.grey,
child: GestureDetector(
onTap: ()=>displayMessage("an item was charged successfully", context),
child: Padding(
padding: const EdgeInsets.all(10),
child: Container(
color: Colors.green,
child: const Center(
child: Text("charge",style: TextStyle(color: Colors.white),),
),
),
),
),
),
// the second container
SizedBox(
width: deviceSize.width,
height: deviceSize.height * .1,
child: Row(
children: [
DecoratedBox(
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: SizedBox(
width: deviceSize.width * .8,
child: bloc.isSearch
? TextFormField(
autofocus: true,
controller: controller,
decoration:
const InputDecoration(hintText: "Search"),
onChanged: (value) {
bloc.filterItems(controller.text);
},
)
: DropdownButtonFormField<String>(
// underline: Container(),
// value: "Discounts",
hint: const Padding(
padding: EdgeInsets.only(left: 10),
child: Text('Please choose type'),
),
items: <String>['Discounts', 'All Items']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
),
),
),
DecoratedBox(
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: SizedBox(
width: deviceSize.width * .2,
child: IconButton(
onPressed: () {
bloc.toggleSearch();
if (!bloc.isSearch) {
bloc.filterItems('');
}
},
icon: Icon(
!bloc.isSearch ? Icons.search : Icons.close)),
),
)
],
),
),
// the third container
if (state is IsLoading || state is SalesInitial)
const Center(
child: CircularProgressIndicator(
color: Colors.green,
backgroundColor: Colors.green,
),
),
if (state is Loaded || state is IsSearch || state is SearchDone)
bloc.items.isEmpty
? const Center(
child: Text("no items added yet"),
)
: Expanded(
child: bloc.filteredItems.isEmpty
? const Center(
child: Text(
"no items found with this name",
style: TextStyle(color: Colors.green),
),
)
: ListView.builder(
itemCount: bloc.filteredItems.length,
itemBuilder: (context, i) {
final item = bloc.filteredItems[i];
return Card(
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.green,
radius: 20,
child: Text(item.price),
),
title: Text(item.name),
subtitle: Text(item.barcode),
trailing: Column(
children: [
IconButton(
onPressed: () {
showAlertDialog(context,item.name);
// bloc.deleteItem(item.name).then((value) {
// bloc.getAllItems();
// });
},
icon: const Icon(
Icons.delete,
color: Colors.red,
))
],
)),
);
}))
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: ()async {
Navigator.of(context).pushNamed(Routes.createItemRoute);
},
),
);
},
);
}
}
the CreateItem screen
class _CreateItemState extends State<CreateItem> {
final nameController = TextEditingController();
final priceController = TextEditingController();
final costController = TextEditingController();
final skuController = TextEditingController();
final barcodeController = TextEditingController();
final inStockController = TextEditingController();
bool each = true; // bool variable for check box
bool isColor = true;
bool switchValue = false;
File? file;
String base64File = "";
String path = "";
final _formKey = GlobalKey<FormState>();
#override
void dispose() {
nameController.dispose();
priceController.dispose();
costController.dispose();
skuController.dispose();
barcodeController.dispose();
inStockController.dispose();
super.dispose();
}
Future pickImage(ImageSource source) async {
File? image1;
XFile imageFile;
final imagePicker = ImagePicker();
final image = await imagePicker.pickImage(source: source);
imageFile = image!;
image1 = File(imageFile.path);
List<int> fileUnit8 = image1.readAsBytesSync();
setState(() {
base64File = base64.encode(fileUnit8);
});
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return BlocProvider(
create: (BuildContext context) => CreateItemCubit(),
child: Builder(builder: (context){
final bloc=BlocProvider.of<CreateItemCubit>(context);
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () => Navigator.of(context).pushNamedAndRemoveUntil(Routes.newSalesRoute, (route) => false),
icon: const Icon(Icons.arrow_back)),
title: const Text("Create Item"),
actions: [TextButton(onPressed: () {}, child: const Text("SAVE"))],
),
body: Padding(
padding: const EdgeInsets.all(10),
child: Form(
key: _formKey,
child: ListView(
children: [
TextFormField(
controller: nameController,
cursorColor: ColorManager.black,
decoration: const InputDecoration(hintText: "Name"),
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return "name can't be less than 5 chars";
}
return null;
},
),
gapH24,
Text(
"Category",
style: TextStyle(color: ColorManager.grey),
),
SizedBox(
width: deviceSize.width,
child: DropdownButtonFormField<String>(
// value: "Categories",
hint: const Padding(
padding: EdgeInsets.only(left: 10),
child: Text('No Category'),
),
items: <String>['No Category', 'Create Category']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
),
),
gapH24,
const Text(
"Sold by",
style: TextStyle(color: Colors.black),
),
gapH24,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: each,
onChanged: (inputValue) {
setState(() {
each = !each;
});
},
),
gapW4,
const Text(
"Each",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
gapH24,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: !each,
onChanged: (inputValue) {
setState(() {
each = !each;
});
},
),
gapW4,
const Text(
"Weight",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
TextFormField(
controller: priceController,
decoration: InputDecoration(
hintText: "Price",
hintStyle: TextStyle(color: ColorManager.grey)),
validator: (value) {
if (value!.isEmpty) {
return "price can,t be empty";
}
return null;
},
),
gapH4,
Text(
"leave the field blank to indicate price upon sale",
style: TextStyle(color: ColorManager.grey),
),
gapH20,
Text(
"Cost",
style: TextStyle(color: ColorManager.grey),
),
TextFormField(
controller: costController,
decoration: InputDecoration(
hintText: "cost",
hintStyle: TextStyle(color: ColorManager.black)),
validator: (value) {
if (value!.isEmpty) {
return "cost can't be empty";
}
return null;
},
),
gapH20,
Text(
"SKU",
style: TextStyle(color: ColorManager.grey),
),
TextFormField(
controller: skuController,
decoration: InputDecoration(
hintText: "Sku",
hintStyle: TextStyle(color: ColorManager.black)),
validator: (value) {
if (value!.isEmpty) {
return "Sku can't be empty";
}
return null;
},
),
gapH30,
TextFormField(
controller: barcodeController,
decoration: InputDecoration(
hintText: "Barcode",
hintStyle: TextStyle(color: ColorManager.grey)),
validator: (value) {
if (value!.isEmpty) {
return "Barcode can't be empty";
}
return null;
},
),
gapH30,
// Divider(thickness: 1,color: ColorManager.black,),
Text(
"Inventory",
style: TextStyle(
color: ColorManager.green,
fontSize: 15,
fontWeight: FontWeight.bold),
),
// ListTile(
// title: Text("TrackStock",style: TextStyle(color: ColorManager.green,fontSize: 15,fontWeight: FontWeight.bold)),
// trailing: Switch(value: switchValue, onChanged: (bool value) {
// setState(() {
// switchValue=!switchValue;
// });
// },),
// ),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("TrackStock",
style: TextStyle(
color: ColorManager.grey,
fontSize: 15,
fontWeight: FontWeight.bold)),
Switch(
value: switchValue,
onChanged: (bool value) {
setState(() {
switchValue = !switchValue;
});
},
),
],
),
gapH10,
if (switchValue)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"in stock",
style:
TextStyle(color: ColorManager.grey, fontSize: 15),
),
TextFormField(
keyboardType: TextInputType.number,
controller: inStockController,
decoration: const InputDecoration(hintText: "0"),
validator: (value) {
if (value!.isEmpty) {
return "value can't be empty";
}
return null;
},
)
],
),
gapH20,
Text(
"Representation in POS",
style: TextStyle(
color: ColorManager.green,
fontSize: 15,
fontWeight: FontWeight.bold),
),
gapH15,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: isColor,
onChanged: (inputValue) {
setState(() {
if (!isColor) {
isColor = !isColor;
}
});
},
),
gapW4,
const Text(
"Color and Shape",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
gapH10,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: !isColor,
onChanged: (inputValue) {
setState(() {
if (isColor) {
isColor = !isColor;
}
});
},
),
gapW4,
const Text(
"Image",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
isColor
? GridView.builder(
physics:
const NeverScrollableScrollPhysics(), // to disable GridView's scrolling
shrinkWrap: true, // You won't see infinite size error
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0,
),
itemCount: containers().length,
itemBuilder: (BuildContext context, int index) {
return containers()[index];
},
)
: Padding(
padding: const EdgeInsets.all(10),
child: Row(
children: [
Expanded(
flex: 1,
child: base64File == ""
? const Icon(Icons.person)
: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(5)),
child: Image.memory(
base64.decode(base64File)))),
gapW4,
Expanded(
flex: 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () =>
pickImage(ImageSource.camera),
child: Row(
children: [
Icon(
Icons.camera_alt,
color: ColorManager.black,
),
gapW8,
Text(
"Take a photo",
style: TextStyle(
color: ColorManager.black,
),
)
],
),
),
const Divider(
thickness: 1,
color: Colors.grey,
),
TextButton(
onPressed: () =>
pickImage(ImageSource.gallery),
child: Row(
children: [
Icon(Icons.camera_alt,
color: ColorManager.black),
gapW8,
Text(
"Choose from gallery",
style: TextStyle(
color: ColorManager.black,
),
)
],
),
)
],
),
)
],
),
)
],
),
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.save,color: Colors.white,),
onPressed: () async {
bool isValid = _formKey.currentState!.validate();
if (isValid) {
FocusScope.of(context).unfocus();
ItemModel? item=await bloc.checkItem(nameController.text);
if(item!=null){
displayMessage("this item was inserted before", context);
}else{
int? res=await bloc.saveItem(ItemModel(
nameController.text,
priceController.text,
costController.text,
skuController.text,
barcodeController.text));
if(res!=null){
displayMessage("an item was inserted successfully", context);
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context)=>const NewSales()), (route) => false);
}
}
}
},
),
);
}
),
);
}
}
this is the SaleCubit
class SalesCubit extends Cubit<SalesState> {
SalesCubit() : super(SalesInitial());
bool isSearch=false;
ItemDBHelper db=ItemDBHelper();
List<ItemModel> items=[];
List<ItemModel> filteredItems=[];
String bsResult='Unknown'; //barcode search result
void toggleSearch(){
isSearch=!isSearch;
emit(IsSearch());
}
void setBarcodeResult(String value){
bsResult=value;
emit(SearchDone());
}
void filterItems(String query){
// emit(Searching());
query.isEmpty?
filteredItems=items:
filteredItems=items.where((item) => item.name.toLowerCase().contains(query.toLowerCase())).toList();
emit(SearchDone());
}
Future<List<ItemModel>?> getAllItems()async{
try{
emit(IsLoading());
items=await db.getAllItems();
filteredItems=items;
print(items);
return items;
}finally{
emit(Loaded());
}
}
Future<void> deleteItem(String name)async{
await db.deleteItem(name);
emit(SearchDone());
}
}
this is the SalesState
part of 'sales_cubit.dart';
#immutable
abstract class SalesState {}
class SalesInitial extends SalesState {}
class IsSearch extends SalesState {}
class IsLoading extends SalesState {}
class Loaded extends SalesState {}
class Searching extends SalesState {}
class SearchDone extends SalesState {}
I have been implementing a search bar in Flutter, which works as expected when searching according to usernames, but does not display all the users when it is empty.
It only displays all the users when typing something in the search bar and completely backspacing it. The following code snippet shows its implementation:
class UsersTable extends StatefulWidget {
List<User> users;
List<Library> posts;
UsersTable(
this.users,
this.posts, {
Key? key,
}) : super(key: key);
#override
State<UsersTable> createState() => _UsersTableState();
}
class _UsersTableState extends State<UsersTable> {
List<User> _foundUsers = [];
#override
initState() {
// at the beginning, all users are shown
Future.delayed(Duration.zero, () async {
_foundUsers = widget.users;
print(_foundUsers.length);
if (mounted) setState(() {});
});
super.initState();
}
// This function is called whenever the text field changes
void _runFilter(String enteredKeyword) {
List<User> results = [];
if (enteredKeyword.trim().isEmpty) {
// if the search field is empty or only contains white-space, we'll display all users
results = widget.users;
print("if filter length");
print(results.length);
} else {
results = widget.users
.where((user) => user.username
.toLowerCase()
.contains(enteredKeyword.toLowerCase()))
.toList();
// we use the toLowerCase() method to make it case-insensitive
}
// Refresh the UI
setState(() {
_foundUsers = results;
});
}
Widget body(BuildContext context, List<User> users, List<Library> posts) {
return SafeArea(
child: Material(
child: Container(
padding: const EdgeInsets.all(defaultPadding),
decoration: const BoxDecoration(
color: boxColor,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
const Align(
alignment: Alignment.center,
child: Text(
"Active Users",
//style: Theme.of(context).textTheme.subtitle1,
style: TextStyle(
color: Colors.white,
fontSize: 20,
decoration: TextDecoration.none),
)),
const SizedBox(
height: 30,
),
TextField(
style: const TextStyle(color: Colors.white),
onChanged: (value) => _runFilter(value),
decoration: const InputDecoration(
labelStyle: TextStyle(color: Colors.white38),
labelText: 'Search',
suffixIcon: Icon(Icons.search),
suffixIconColor: Colors.white),
),
const SizedBox(
height: 20,
),
// SizedBox(
//width: double.infinity,
// child: SingleChildScrollView(
Container(
child: DataTable(
columnSpacing: 7,
columns: const [
// DataColumn(
// label: Text(
// "First Name",
// style: TextStyle(color: Colors.white),
// ),
// ),
// DataColumn(
// label: Text(
// "Last Name",
// style: TextStyle(color: Colors.white),
// ),
// ),
DataColumn(
label: Text(
"Username",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
DataColumn(
label: Text(
"Email ID",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
// DataColumn(
// label: Text(
// "DOB",
// style: TextStyle(color: Colors.white),
// ),
// ),
DataColumn(
label: Text(
"Account\nType",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
DataColumn(
label: Text(
"Delete\nUser",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
DataColumn(
label: Text(
"View\nPosts",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
],
rows:
//_foundUsers.isNotEmpty?
_foundUsers
.map(
(user) => DataRow(
cells: <DataCell>[
// DataCell(Text(user.first_name,
// style: TextStyle(color: Colors.white))),
// DataCell(Text(user.last_name,
// style: TextStyle(color: Colors.white))),
DataCell(Text(user.username,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white))),
DataCell(Text(user.email,
style: TextStyle(color: Colors.white))),
// DataCell(Text(user.date_of_birth,
// style: TextStyle(color: Colors.white))),
DataCell(Text(user.account_type,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white))),
DataCell(
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.purple,
padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 15),
textStyle: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold),
shadowColor: Colors.grey,
),
onPressed: () {
// if (user.username
// .compareTo('hwumazijadmin48') !=
// 0) {
BlocProvider.of<AuthenticationBloc>(context)
.add(DeleteUser(
username: user.username));
// } else {
// const Text("Cannot Delete Admin");
// }
},
child: const Text('X'),
),
),
DataCell(
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.purple,
padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 15),
textStyle: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold),
shadowColor: Colors.grey,
),
onPressed: () {
List<Library> po = [];
int i = 0;
while (i < posts.length) {
if (posts[i]
.user
.compareTo(user.username) ==
0) {
po.add(posts[i]);
}
i++;
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PostsTable(po),
),
);
},
child: const Text('\u{1F441}'),
),
),
],
),
)
.toList()
//: []
),
),
// ),
],
),
)
//)
));
}
Am I missing something in the code?
move super.initState(); above and remove Future.delayed.
#override
initState() {
super.initState();
_foundUsers = widget.users;
}
no need to setState({}); because build method will trigger after initState. Also no need for mounted because we removed asyncoperation.
I am having 2 rounded checkboxes. How can i make only one checkbox to be check at time without using package. I will be appreciate if you could help me.
CODE :-
Checkbox(
value: prepaidCheckBoxValue,
shape: const CircleBorder(),
checkColor: Colors.white,
onChanged: (value) {
prepaidCheckBoxValue = !prepaidCheckBoxValue;
//print(prepaidCheckBoxValue);
setState(() {
selectedPaymentType = 'Prepaid';
});
},
),
const Text(
'Prepaid',
style: TextStyle(
fontSize: 20.0,
),
),
Checkbox(
value: podCheckBoxValue,
shape: const CircleBorder(),
checkColor: Colors.white,
onChanged: (value) {
podCheckBoxValue = !podCheckBoxValue;
setState(() {
selectedPaymentType = 'Pay on delivery';
});
//print(value);
},
),
const Text(
'Pay on Delivery',
style: TextStyle(
fontSize: 20.0,
),
),
Instead of a Checkbox you can use a RadioButton which is meant to do that
Like this
class MyRadioButton extends StatefulWidget {
#override
State<MyRadioButton> createState() => _MyRadioButtonState();
}
class _MyRadioButtonState extends State<MyRadioButton> {
var val;
#override
Widget build(BuildContext context) {
return Row(
children: [
Radio(
value: 1,
groupValue: val,
onChanged: (value) {
setState(() {
val = value;
});
},
),
const Text(
'Prepaid',
style: TextStyle(
fontSize: 20.0,
),
),
Radio(
value: 2,
groupValue: val,
onChanged: (value) {
setState(() {
val = value;
});
},
),
const Text(
'Pay on Delivery',
style: TextStyle(
fontSize: 20.0,
),
),
],
);
}
}
I have dynamic List as shown below:
List<List<dynamic>> _userTransactionList;
The List contains these values:
[
[12.9, test, 80, 357.24, James],
[88.0, test, 19, 357.24, Carol],
[196.55, test, 34, 357.24, Matthew],
[48.0, test, 59, 357.24, Brown]
]
As shown above, my _userTransactionList length is 4. I need 3 column as:
Name Age Amount
And row cell will be:
Name Age Amount
James 80 12.9
Carol 19 88.0
Matthew 34 199.55
Brown 59 48.0
I can place the cell value manually as shown below, but I don't know how to get those value from list and add to row cells dynamically. Because of my List<List> _userTransactionList values comes from remote server I need to fill DataTable dynamically. Any idea?
Manual Code:
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columnSpacing: 30.0,
columns: <DataColumn>[
DataColumn(
label: Text(
'Name',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
DataColumn(
label: Text(
'Age',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
DataColumn(
label: Text(
'Amount',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
DataColumn(
label: Text(
'Mail',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
],
rows: <DataRow>[
DataRow(
cells: <DataCell>[
DataCell(Text('James')),
DataCell(Text('80')),
DataCell(Text('12.9')),
DataCell(
IconButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('James 80 12.9'),
),
);
},
icon: Icon(
Icons.email_outlined,
color: Colors.red,
),
),
),
],
),
DataRow(
cells: <DataCell>[
DataCell(Text('Carol')),
DataCell(Text('19')),
DataCell(Text('88.0')),
DataCell(
IconButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Carol 19 88.0'),
),
);
},
icon: Icon(
Icons.email_outlined,
color: Colors.red,
),
),
),
],
),
DataRow(
cells: <DataCell>[
DataCell(Text('Matthew')),
DataCell(Text('34')),
DataCell(Text('199.55')),
DataCell(
IconButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Matthew 34 199.55'),
),
);
},
icon: Icon(
Icons.email_outlined,
color: Colors.red,
),
),
),
],
),
DataRow(
cells: <DataCell>[
DataCell(Text('Brown')),
DataCell(Text('59')),
DataCell(Text('48.0')),
DataCell(
IconButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Brown 59 48.0'),
),
);
},
icon: Icon(
Icons.email_outlined,
color: Colors.red,
),
),
),
],
),
],
),
);
Full Code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: Text(_title)),
body: MyStatelessWidget(),
),
);
}
}
class MyStatelessWidget extends StatelessWidget {
List<List<dynamic>> _userTransactionList = [
[12.9, "BxC", 80, 357.24, "James"],
[88.0, "ArD", 19, 145.00, "Carol"],
[196.55, "VsT", 34, 18.60, "Matthew"],
[48.0, "IhO", 59, 92.19, "Brown"]
];
#override
Widget build(BuildContext context) {
List<DataRow> rows = [];
for (var i = 0; i < _userTransactionList.length; i++) {
rows.add(DataRow(cells: [
DataCell(
Text(_userTransactionList[i][4].toString()),
),
DataCell(
Text(_userTransactionList[i][2].toString()),
),
DataCell(
Text(_userTransactionList[i][0].toString()),
),
DataCell(
IconButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Matthew 34 199.55'),
),
);
},
icon: Icon(
Icons.email_outlined,
color: Colors.red,
),
),
),
]));
}
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
//child: _getData01(_userTransactionList, context)
child: DataTable(
columnSpacing: 30.0,
columns: <DataColumn>[
DataColumn(
label: Text(
'Name',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
DataColumn(
label: Text(
'Age',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
DataColumn(
label: Text(
'Amount',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
DataColumn(
label: Text(
'Mail',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
),
),
],
rows: rows,
));
}
}
I am new to flutter and I could not do searching of data in datatable in my flutter project.
Please anyone help me how to achieve this functionality in datatable. So that when I click on search box as per the name, I will be able to find that data in my table.
Thanks in advance.
Below is my code.
patient.dart
class PatientInfo{
String profile_pic;
String name;
int age;
String assigned_slots;
String completed_slots;
PatientInfo({this.profile_pic, this.name, this.age, this.assigned_slots, this.completed_slots});
}
var details = <PatientInfo>[
PatientInfo(
profile_pic: 'https://s3.amazonaws.com/empoweringparents-uploads/young-children-back-to-school-fb.jpg',
name: 'A',
age: 9,
assigned_slots: 'yes',
completed_slots: 'yes'
),
PatientInfo(
profile_pic: 'https://www.freeiconspng.com/thumbs/school-children-png/school-children-png-5.png',
name: 'Lucy',
age: 10,
assigned_slots: 'yes',
completed_slots: 'No'
),
PatientInfo(
profile_pic: 'https://images.unsplash.com/photo-1552457309-e45be97707ce?ixid=MXwxMjA3fDB8MHxzZWFyY2h8NHx8aW5kaWFuJTIwY2hpbGR8ZW58MHx8MHw%3D&ixlib=rb-1.2.1&w=1000&q=80',
name: 'Susan',
age: 12,
assigned_slots: 'yes',
completed_slots: 'yes'
),
PatientInfo(
profile_pic: 'https://assets.theindusparent.com/wp-content/uploads/sites/9/gallery/top-9-things-you-should-never-do-to-you-babies/137448603.jpg',
name: 'Peter',
age: 14,
assigned_slots: 'No',
completed_slots: 'yes'
),
PatientInfo(
profile_pic: 'https://s3.amazonaws.com/empoweringparents-uploads/young-children-back-to-school-fb.jpg',
name: 'Edmund',
age: 15,
assigned_slots: 'yes',
completed_slots: 'No'
),
];
homescreen.dart
class PatientDetails extends StatefulWidget {
#override
_PatientDetailsState createState() => _PatientDetailsState();
}
class _PatientDetailsState extends State<PatientDetails> {
TextEditingController nameController = TextEditingController();
Widget bodyData(){
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
onSelectAll: (b) {},
sortColumnIndex: 1,
sortAscending: true,
columns: <DataColumn>[
DataColumn(
label: Text('Profile'),
numeric: false,
onSort: (i, b){
// setState(() {
// ......
// });
print('$i $b');
},
),
DataColumn(
label: Text('Name'),
numeric: false,
onSort: (i, b){
setState(() {
details.sort((a, b) => a.name.compareTo(b.name));
});
print('$i $b');
},
),
DataColumn(
label: Text('Age'),
numeric: false,
onSort: (i, b){
// setState(() {
//.....
// });
print('$i $b');
},
),
DataColumn(
label: Text('Assigned Slots'),
numeric: false,
onSort: (i, b){
// setState(() {
//......
// });
print('$i $b');
},
),
DataColumn(
label: Text('Completed Slots'),
numeric: false,
onSort: (i, b){
// setState(() {
//........
// });
print('$i $b');
},
)
],
rows: details.map((detail)=> DataRow(
cells: [
DataCell(CircleAvatar(radius: 25, backgroundImage: NetworkImage(detail.profile_pic),)),
DataCell(Text(detail.name), showEditIcon: false),
DataCell(Text(detail.age.toString()), showEditIcon: false),
DataCell(Text(detail.assigned_slots), showEditIcon: false),
DataCell(Text(detail.completed_slots), showEditIcon: false)
],
),
).toList()
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarSection('Patient Details'),
body: Container(
child: bodyData(),
),
);
}
Widget appBarSection(String title){
return AppBar(
title: Text(title),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 150,
child: TextFormField(
controller: nameController,
decoration: InputDecoration(
hintText: "Search",
hintStyle: TextStyle(fontSize: 16, color: Colors.white),
isDense: true,
suffixIcon: Icon(Icons.search, color: Colors.white),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Colors.white,
width: 2.0,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(style: BorderStyle.none),
),
filled: true,
fillColor: Colors.lightBlue.shade200,
),
),
),
),
],
);
}
}
Please help me!