I have a ListView.builder that contains a number of CustomCards:
ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return CustomCard(
data: list[index],
}
),
The CustomCard widgets contain a TextField that can be edited. When the user has changed the data from the CustomCard widgets, the data should be saved by pressing a button. I inserted a screenshot for an easier understanding:
My problem is now how to access the data from the ListView / CustomCards. Here Rémi Rousselet wrote that "in Flutter data can only be passed downward". Therfore I can not add the wanted data to a constructor or use a BuildContext. This answer from Günter Zöchbauer says that it is expensive to use GlobalKeys for ListViews. Another idea would be to merge the two widgets into one and use a TextEditingController like suggested here by João Soares. I think this would in my case lead to really messy code that I try to avoid.
How can I realize saving data from all CustomCards of the ListView at the same time? What is the easiest, least expensive and cleanest way to do it? Is there a concept that I do not know or do not undestand correctly?
CodePudding user response:
I think you want to have two inputs at each line in the ListView widget, I hope the example below is helpful.
Solution ^^
create a class in which you declare a list of TextEditingController
class _HomePageState extends State<HomePage> {
List<CustomCardController> _customCardControllers = [];
List<CustomCard> _customCards = []
..add(CustomCard("US","UK"))
..add(CustomCard("TUNSIA","JAPON"))
..add(CustomCard("JAPON","CANADA"))
;
@override
void initState() {
super.initState();
_customCardControllers = List.generate(_customCards.length,
(index) => CustomCardControllers(_customCards[index]));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("test"),
),
body: Center(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount: _customCardControllers.length,
itemBuilder: (context, index) {
return
_creatCustomCard(_customCardControllers[index].customCard,index);
}
),
ElevatedButton(onPressed: getAllValues, child:
Text("SAVE"))
],
),
),
);
}
Widget _creatCustomCard(CustomCard customCard,int index) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
key: UniqueKey(),
children: [
Row(
children: [
Expanded(child: Text("${customCard.arrival}"),flex: 1),
Expanded(child: Text("
${customCard.departure}"),flex: 1),
],
),
Row(
children: [
Expanded(
flex:1,
child: TextField(
controller:
_customCardControllers[index].textEditingControllers![0],
),
),
Expanded(
flex:1,
child: TextField(
controller:
_customCardControllers[index].textEditingControllers![1],
),
),
],
),
SizedBox(height: 15,)
],
);
}
void getAllValues() {
for(int i=0;i<_customCards.length;i ){
String value1
=_customCardControllers[i].textEditingControllers![0].text;
String value2
=_customCardControllers[i].textEditingControllers![1].text;
print("$i : arrival ${_customCards[i].arrival} : $value1 |
departure ${_customCards[i].departure} : $value2");
}
}
}
class CustomCardController{
final CustomCard customCard;
List<TextEditingController> ? textEditingControllers;
CustomCardController(this.customCard){
textEditingControllers = []
..add(new TextEditingController())
..add(new TextEditingController());
}
}
class CustomCard{
final String arrival;
final String departure;
CustomCard(this.arrival, this.departure);
}
[![enter image description here][1]] [1]: https://i.stack.imgur.com/b0NTr.png