I am trying to create a 'create a task' page where the user can add or delete todo textfields for the task. I created a list of TextEditingControllers to dynamically add and remove from it for mapping them to textformfields.. I have no issue in adding but when i try to remove a specific TextEditingController (either by index or by reference) from the list, it always result in removing the last textformfield..
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gdsc_session2/constants/image_strings.dart';
import '../widgets/text_field.dart';
class NewTask extends StatefulWidget {
const NewTask({super.key});
@override
State<NewTask> createState() => _NewTaskState();
}
class _NewTaskState extends State<NewTask> {
final GlobalKey<FormState> formKey = GlobalKey();
final List<TextEditingController> controllers = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Form(
key: formKey,
child: ListView(
children: [
for (var ctrl in controllers) ...[
GTextField(
hintText: 'Todo ${controllers.indexOf(ctrl) + 1}',
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SvgPicture.asset(
GImageStrings.clipboard,
width: 25,
),
),
suffixIcon: IconButton(
// Delete Button
onPressed: () {
setState(() {});
removeTextField(controllers.indexOf(ctrl));
},
icon: const Icon(Icons.clear)),
controller: ctrl,
),
const SizedBox(
height: 15,
),
],
// Add Button
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 200,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue.withOpacity(0.2),
),
onPressed: () {
setState(() {
addTextField();
});
},
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add_circle),
SizedBox(
width: 10,
),
Text(
'Add',
style: TextStyle(color: Colors.white),
)
],
)),
),
],
)
],
),
),
)
],
),
);
}
void addTextField() {
controllers.add(TextEditingController());
}
void removeTextField(int index) {
controllers.removeAt(index);
}
}
and this is my custom textformfield
import 'package:flutter/material.dart';
class GTextField extends StatelessWidget {
final Widget? prefixIcon;
final Widget? suffixIcon;
final String hintText;
final TextEditingController controller;
const GTextField({
super.key,
this.prefixIcon,
this.suffixIcon,
required this.hintText,
required this.controller,
});
@override
Widget build(BuildContext context) {
return TextFormField(
decoration: InputDecoration(
hintText: hintText,
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15),
prefixIcon: prefixIcon,
prefixIconConstraints: const BoxConstraints(),
suffixIcon: suffixIcon,
filled: true,
fillColor: Colors.white10.withOpacity(0.05),
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(30),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(30),
),
),
);
}
}
before trying to delete 'study'
after trying to delete 'study'
I was expecting that the textformfield corrosponding to its controller will be deleted.. but what actually happens is that the last textformfield gets deleted.
TextFormField
is missing a controller property.
Please assign a controller to it.
...
return TextFormField(
controller: controller,
decoration: ...,
);
...