どういうこと?
名前を入力する欄が複数行あった場合、同じTextEditingControllerを使ってしまうと、入力された値が全てに反映されてしまいます。
動的にしたい…
初めから入力する行数がわかっていれば、それぞれのTextEditingController を作ればいいわけですが、行を追加したり削除したりするような処理だといくら数が増えるかわからないわけです。
ReactであればuseFieldArrayという便利なものがあって、fieldに追加したり削除したりで動的に同じ値を持った入力フォームを簡単に作成できるんですが、Flutterではそういうやつがなさそうなので、悩みました…
要はindexで呼び出せばいいってわけ?
TextEditingControllerがリストになっていてループで回したときに指定したindexで欲しいとこのTextEditingControllerが呼び出せればいいから…
List<TextEditingController> nameControllers = List.generate(2, (i) => TextEditingController());
@override
Widget build(BuildContest context) {
return Scaffold(
child: ListView.builder(
shrinkWrap: true,
itemCount: nameControllers.length,
itemBuilder: (context, index) {
return Column(
children: [
TextField(
controller: nameControllers[index],
decoration: InputDecoration(labelText: 'name')
)
]
)
}
)
)}
これでだいたい近いことができました!
でもこれだと、リストを作ってからだから動的ではないな…
あれ?複数のTextEditingControllerがあるときどうするんだ?
例えばメンバー表などで名前と年齢を入力するTextFieldがあり、行を追加したい場合、上記の方法だと、TextEditingControllerを指定できません。
呼び出す時に何かを指定しなきゃならないということは…Mapか?
ということで、
List<Map<String, TextEditingController>> memberControllers = [
{
'name':TextEditingController(),
'age': TextEditingController(),
}
];
で、呼び出す時はListView.builderを使って
ListView.builder(
itemCount: memberControllers.length,
itemBuilder: (context, index) {
return Row(
children: [
SizedBox(
width: 200,
child: TextField(
controller: memberControllers[index]['name'],
decoration: InputDecoration(labelText: 'name')
),
),
const SizedBox(width: 20.0),
SizedBox(
width: 200,
child: TextField(
controller: memberControllers[index]['age'],
decoration: InputDecoration(labelText: 'age')
)
)
]);
}
)
これでそれぞれを呼び出すことができました。
あとは行を追加するボタンとかをおもむろに追加します。
ElevatedButton.icon(
onPressed: () {
setState(() {
memberControllers.add({
'name': TextEditingController(),
'age': TextEditingController(),
});
});
},
icon: const Icon(Icons.add),
label: const Text('追加')
),
解決
これでやりたいことができました。
調べ方が悪いのか求めることがなかなか出てこなかったので、なんとかかんとかやってみました。
動いてはいますが、やり方が正しいか不安なので、こうしたほうがいい、このやりかたは良くないなどありましたらぜひコメントくださると嬉しいです。
お読みいただきありがとうございました。
参考
参考にさせていただきました。ありがとうございます。