Flutter DataTable -Tap on entire Row - flutter

im new to Flutter. I need help on OnTap in DataCell. For example, instead of tapping one cell, I want the Row.
Heres my codes
DataTable(
columns: <DataColumn>[
DataColumn(
label: Text("Title"),
),
DataColumn(
label: Text("Contacts"),
),
)
],
rows: contracts.map((contract) => DataRow(
cells: [
DataCell(Text(contract.title),
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => List(),),
);
}),
DataCell(Text(contract.contacts),
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => List(),),
);
}),).toList()
i want to click on a specific row and it will route to another page also sends the index value of it.

Had the same issue, realised you could use the onSelectChanged from the DataRow.
Example from the DataTable
rows: searchList.map((item) {
return DataRow(
onSelectChanged: (bool value) {
// ENTER CALLBACK HERE (It's not restricted to use the bool)
},
cells: ...
Note, this will make the Checkbox visible, if you do not require this then make sure you force the showCheckboxColumn to false in the DataTable:
return DataTable(
showCheckboxColumn: false,
columns: [...]

To make the entire widget tappable
just wrap your widget with
InkWell() or GestureDetector Widget
InkWell() widget will add a clickable shadow kind of effect when you press on the widget
whereas GestureDetector() widget won't
In your case instead of wrapping DataCell just wrap your DataRow widget

There's a property in DataRow you can implement called onSelectChanged where you can put your function inside.
bool isSelected = false;
DataRow(
selected: isSelected,
onSelectChanged: (x) {
setState(() {
isSelected = x;
});
},
cells: <DataCell>[
DataCell(
Text('Row1'),
),
],
),

Try using DataRow.byIndex(), then use that index when wrapping your DataRow in a GestureDetector.

Related

How to delete a row from a DataTable in Flutter?

I'm new to flutter. I'm creating a app with a table which a button in every row. I need to delete the row when that button is pressed.
This is the code of the table.
DataTable(
columns: const <DataColumn>[
DataColumn(label: Text('Medications')),
DataColumn(label: Text('Amount')),
DataColumn(label: Text('When')),
DataColumn(label: Text(' '))
],
rows:
_data // Loops through dataColumnText, each iteration assigning the value to element
.map(
((element) => DataRow(
cells: <DataCell>[
DataCell(Text(element[
"drug"])), //Extracting from Map element the value
DataCell(Text(element["amount"])),
DataCell(Text(element["when"])),
DataCell(new RButton(
id: bid,// bid variable increments by 1 every t
onPressed: onPressed,
))
],
)),
)
.toList(),
),
This is the code of RButton
class RButton extends StatelessWidget {
final int id;
final Function onPressed;
const RButton({this.id, this.onPressed});
#override
Widget build(BuildContext context) {
return SizedBox(
width: 30,
child: FlatButton(
onPressed: () {
onPressed(this.id);
print(this.id);
},
textColor: Colors.red,
child: Text("-"),
));
}
}
This is the code of the function button run when pressed.
onPressed(id) {
setState() {
_data.remove(_data[id]);
}
}
Assuming that you are properly using a StatefulWidget to create this example.
setState is a function that takes another function as it's single parameter.
So, it must used like this,
onPressed(id) {
setState(() {
_data.remove(_data[id]);
});
}

Dynamic adding and removing elements from Widget list

I want to create a list of widgets(TextFormField) in which I can add a new element with button Add, and remove any element with the button next to that element. So I would have unknown number of TextFormFields in array and would be able to add a new one, and destroy any one TextFormField.
I was able to make adding of new TextFormFields but removing only works if I want to remove last one.
Is there any way to determine the index of removeButton that was clicked?
List<Widget> proba = new List<Widget>();
List<TextEditingController> _controllers = new List<TextEditingController>();
...
IconButton(
icon: Icon(Icons.add_circle_outline),
onPressed: () {
setState(() {
_controllers.add(new TextEditingController());
});
setState(() {
proba.add(Row(
children: [
Icon(Icons.radio_button_unchecked),
Expanded(
child: TextFormField(
controller: _controllers[_controllers.length - 1],
decoration:
InputDecoration(hintText: "Add text..."),
),
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
_controllers.removeAt(_controllers.length - 1);
proba.removeAt(proba.length - 1);
});
},
)
],
));
});
},
),
Adding works fine. The code removes last element but I would like to remove the element whose button was clicked.
I think you could use a ListView (for example with the builder constructor), so that each Row is a ListTile. The itemBuilder builds the item and you have access to the index. It would look something like this:
int itemCount = 3;
ListView.builder(
itemCount: _counter,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.radio_button_unchecked),
title: TextFormField(),
trailing: IconButton(
onPressed: () {
setState(() {
_counter--;
});
},
icon: Icon(Icons.delete),
),
);
},
),
In the setState Method in the onPressed property you have access to the index. In the example the ListView takes care to create the ListTiles based on the itemCount. You might want to create a list of objects instead of just the int itemCount to store data (maybe the text in the TextFormField). But you can still delete the item based on the index from the itemBuilder: values.deleteAt(index).
Have a look at the docs for the ListView and the ListTile classes:
https://api.flutter.dev/flutter/widgets/ListView-class.html
https://api.flutter.dev/flutter/material/ListTile-class.html

Define navigation route for each element in a String List flutter

I have a list of string which is a Text and each of this List should move me to a specific screen or action, at the momnent I am stuck into this issue, how to assign to each of the list a different route?
this is the code:
List<String> items = [
'Spedizioni',
'I Tuoi ordini',
'Aggiungi un Prodotto',
'Contattaci'
];
child: Row(
children: [
Text(
items[i],
style: TextStyle(
color: _isHovering[i]
? Theme.of(context).primaryTextTheme.button.decorationColor
: Theme.of(context).primaryTextTheme.button.color,
),
),
SizedBox(width: 5,),
Icon(icons[i]),
]
),
);
and until here all ok because it show different item into the list but now I want each of this item in the list navigate to a route as now I defined just one, but I need to define different route for different item in the List
onTap: () {
showDialog(
context: context,
builder: (context) => AddingProductsPopup(),
);
},
Please help me to go out from this stuck
based on your full code https://codeshare.io/an0jpv you can achieve that by like following :
onTap: () {
//here should have the options to call a different route for different List item menu
// call for our alert dialog widget including one more variable which is `items[i]` that has the text that would be passed to the alert
onPressed: () {
//here we show the pop up and pass the variable to it
showAlert(context, items[i]);
setState(() {});
},
now let's define our alert widget
showAlert(BuildContext context, String myItem) {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text("this is the clicked item $myItem",);});
});
);
},
now when the popup shows and based on the received text from items[i] the dialog can have deferent titles , and you can add deferent conditions to adjust the content based on the text received from the press item;

Flutter display sql data in ListTile instead of DataCell

I am displaying a list of data fetched from my sql database using DataCell, but I don't really like how it looks and want to switch it to display it using ListTile, this is the code that I am using to display it using DataCell:
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(
label: Text(''),
)
],
rows: _chatUsers
.map(
(user) => DataRow(cells: [
DataCell(
Text(user.firstNameUser),
// Add tap in the row and populate the
// textfields with the corresponding values to update
onTap: () {
// Set the Selected employee to Update
_selectedUser = user;
setState(() {
});
},
),
]),
)
.toList(),
),
),
);
You need to use the ListView widget for this.
There is a lot explained in that API reference section, I think you will be able to rework you app after reading.
So you will have a ListView with the childrenproperty set to smth like
_chatUsers
.map(
(user) =>
ListTile(
title: Text(user.firstNameUser),
// Add tap in the row and populate the
// textfields with the corresponding values to update
onTap: () {
// Set the Selected employee to Update
_selectedUser = user;
setState(() {
});
},
),
)
.toList()

What is the correct way to use PopUpMenuItem onTap/onPessed in Flutter?

What is the correct way to call a function in Flutter when PopupMenuItem is tapped? Because inherently the widget does not have a onTapped property. The only thing close to it is setting the value of the PopupMenuItem widget. So the way I approached it is to set the state in the onSelected parameter in the PopupMenuButton. I did not find anyone talking about this situation on the internet so I thought it is worth to get opinions from other. Is this the proper way to do this?
I have tried to use a FlatButton as the child of the PopupMenuButton, but it did not work. It seemed that the application did not record the onTapped function of the FlatButton.
PopupMenuButton<Choice>(
onSelected: (Choice result) {
setState(() {
_selection = result;
if (_selection == Choice.SIGN_OUT) {
_signOut();
print('[home.dart] _signOut()');
}
});
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<Choice>>[
PopupMenuItem(
child: Text(
'Sign Out',
style: TextStyle(color: Colors.black),
),
value: Choice.SIGN_OUT,
),
],
),
The expected result is to call a function when a PopupMenuItem is tapped.
PopUpMenuItem invocation can be done in two ways now.
We can do it with the onTap method now.
PopupMenuItem(
value: 'share',
onTap: () {
print("hello world");
},
child: Text('Share'),
),
Or it can be done old school like the OP has mentioned.
onSelected: (value) {
switch (value) {
case ('subscribe'):
print('Subscribing');
break;
case ('edit'):
print('editing');
break;
case ('share'):
print('sharing');
break;
default:
return;
}
},