Home > Back-end >  Flutter: A list of generated TextFields deletes item at the final index regardless of the index pass
Flutter: A list of generated TextFields deletes item at the final index regardless of the index pass

Time:08-09

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,
            ),
          ),
        ),
      ],
    );
  }
}
  • Related