Assuming I have created 10 fields and use the delete button at index 2, the fields reduce to 9 but the item in index 10 is deleted instead of deleting 2 and moving up the others. I have written some minimal reproduction of the code Here is the sample code.
import 'package:flutter/material.dart';
void main() {
runApp(const EditFields());
}
class EditFields extends StatefulWidget {
const EditFields({Key? key}) : super(key: key);
@override
State<EditFields> createState() => _EditFieldsState();
}
class _EditFieldsState extends State<EditFields> {
List<String> openRoles = [];
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ShrinkWrap vs Slivers',
home: Scaffold(
appBar: AppBar(
title: const Text("ShrinkWrap"),
),
body: Column(
children: [
...List.generate(
openRoles.length,
(i) {
return Row(
children: [
SizedBox(
width: 300,
child: TextFormField(
maxLines: 1,
key: Key('rolefield$i'),
//..decoration
onChanged: (value) {
setState(() {
openRoles[i] = value!;
});
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: InkWell(
onTap: () {
openRoles.removeAt(i);
setState(() {});
},
child: const Icon(
Icons.delete,
color: Colors.red,
size: 24,
),
),
),
],
);
},
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
primary: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
side: const BorderSide(color: Colors.blue))),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Padding(
padding: EdgeInsets.all(4.0),
child: Icon(
Icons.add_rounded,
size: 25,
color: Colors.blue,
),
),
Text('ADD', style: TextStyle(color: Colors.blue)),
],
),
onPressed: () {
openRoles.add("Text");
setState(() {});
}),
],
),
),
);
}
}
CodePudding user response:
The issue is with using key, once a single item remove key changes by from
List.generate(
openRoles.length,
(i) {
If we do use map instead of list, removing n item, Data will for n> items. We can use TextEditingController
in this case to work properly
class EditFields extends StatefulWidget {
const EditFields({Key? key}) : super(key: key);
@override
State<EditFields> createState() => _EditFieldsState();
}
class _EditFieldsState extends State<EditFields> {
List<TextEditingController> controllers = [];
int counterX = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ShrinkWrap vs Slivers',
home: Scaffold(
appBar: AppBar(
title: const Text("ShrinkWrap"),
),
body: Column(
children: [
for (final c in controllers) rowB(c),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
primary: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
side: const BorderSide(color: Colors.blue))),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Padding(
padding: EdgeInsets.all(4.0),
child: Icon(
Icons.add_rounded,
size: 25,
color: Colors.blue,
),
),
Text('ADD', style: TextStyle(color: Colors.blue)),
],
),
onPressed: () {
controllers.add(TextEditingController());
setState(() {});
}),
],
),
),
);
}
Row rowB(TextEditingController c) {
return Row(
children: [
SizedBox(
width: 300,
child: TextFormField(
maxLines: 1,
controller: c,
//..decoration
onChanged: (value) {
setState(() {});
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: InkWell(
onTap: () {
controllers.remove(c);
setState(() {});
},
child: const Icon(
Icons.delete,
color: Colors.red,
size: 24,
),
),
),
],
);
}
}