AMM
AMM

Reputation: 196

Delete Widget at button press Flutter

Recently implemented a tagForm widget at "+" button press, I want to delete those widgets now at "delete" button press, but right now, even when I press the "delete" button, nothing happens.

How can I solve this?

Any help appreciated!

enter image description here

code:

import 'package:flutter/material.dart';
import '../database/firestoreHandler.dart';
import '../models/todo2.dart';
import '../widgets/dialogs.dart';

class TodoEdit extends StatefulWidget {
  String? doctitle;
  String? doctdescription;
  String? docimage;
  String? docid;
  List? doctags;

  TodoEdit({Key? key, this.doctitle, this.doctdescription, this.docimage, this.docid,this.doctags}) : super(key: key);


  @override
  _TodoEditState createState() => _TodoEditState();

}


class _TodoEditState extends State<TodoEdit> {
  final _formKey = GlobalKey<FormState>();
  final tcontroller = TextEditingController();
  final dcontroller = TextEditingController();
  final icontroller = TextEditingController();

  var textEditingControllers = <TextEditingController>[];
//-----------------the list where the form is stored----------
  var textformFields = <Widget>[];

  void _addformWidget(controller) {
    setState(() {
      textformFields.add(tagForm(controller));
    });
  }
//------------------------------------------------------------------------
  Widget tagForm(controller){

    return TextFormField(
      controller: controller,
      style: TextStyle(color: Colors.white),
      decoration: InputDecoration(
          labelText: "Tag",
          labelStyle: TextStyle(color: Colors.white60),
          fillColor: Colors.black,
          filled: true,
          suffixIcon: IconButton(
            icon:Icon(Icons.delete, color: Colors.white,),
//--------------------- doesn't work?-------------------
            onPressed: (){
              setState(() {
                textformFields.remove(tagForm(controller));
              });
            },
--------------------------------------------------------------
          )
      ),
    );

  }

//-----------------------------------------------------------

  @override
  void initState() {

    super.initState();
    tcontroller.text = widget.doctitle.toString();
    dcontroller.text = widget.doctdescription.toString();
    icontroller.text = widget.docimage.toString();

    widget.doctags?.forEach((element) {
      var textEditingController = new TextEditingController(text: element);
      textEditingControllers.add(textEditingController);
      //return textformFields.add(tagForm(textEditingController)
      return _addformWidget(textEditingController);
      //);
    });
    
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: Colors.grey[900],
      appBar: AppBar(
        actions: [
          IconButton(onPressed: (){
            showDialog(
              barrierDismissible: false,
              context: context,
              builder: (context) {
                return AlertDialog(
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20),
                  ),
                  title: Text('Delete TODO'),
                  actions: [
                    TextButton(
                      child: Text('Cancel'),
                      onPressed: () {
                        Navigator.pop(context);
                      },
                    ),
                    TextButton(
                      child: Text('Delete'),
                      onPressed: () {
                        deleteData(widget.docid.toString(), context);
                        setState(() {
                          showSnackBar(context, 'todo "${widget.doctitle}" successfully deleted!');
                        });
                      },
                    ),
                  ],
                );
              },
            );
          },
              icon: Icon(Icons.delete))
        ],
        backgroundColor: Colors.grey[900],
        title: Text("${widget.doctitle}"),
      ),
      body: Container(
        child: SafeArea(
        child:  Form(
          key: _formKey,
          child: Column(
            children: [
              SizedBox(height: 10),
              TextFormField(
                controller: tcontroller,
                style: TextStyle(color: Colors.white),
                decoration: InputDecoration(
                  labelText: "Title",
                  labelStyle: TextStyle(color: Colors.white60),
                  fillColor: Colors.black,
                  filled: true,
                ),
              ),
              SizedBox(height: 10),
              TextFormField(
                controller: dcontroller,
                style: TextStyle(color: Colors.white),
                decoration: InputDecoration(
                  labelText: "Description",
                  labelStyle: TextStyle(color: Colors.white60),
                  fillColor: Colors.black,
                  filled: true,
                ),
              ),
              SizedBox(height: 10),
              TextFormField(
                controller: icontroller,
                style: TextStyle(color: Colors.white),
                decoration: InputDecoration(
                  labelText: "Image url",
                  labelStyle: TextStyle(color: Colors.white60),
                  fillColor: Colors.black,
                  filled: true,
                ),
              ),
              SizedBox(height: 10),
              Row(children: [
                Text("Tags:", style:TextStyle(color: Colors.white)),
                IconButton(onPressed: (){
                  var textEditingController = new TextEditingController(text: "tag");
                  textEditingControllers.add(textEditingController);
                  _addformWidget(textEditingController);
                  print(textformFields.length);
                },
                  icon: Icon(Icons.add,color: Colors.white,),
                )
              ],),
              /*SingleChildScrollView(
                child: new Column(
                children: textformFields,
                )
              ),*/
              Expanded(
                  child: SizedBox(
                    height: 200.0,
                    child: ListView.builder(
                        itemCount: textformFields.length,
                        itemBuilder: (context,index) {
                          return textformFields[index];
                        }),
                  )
              ),
            ],
          ),
        ),
        ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: (){
            List<String> test = [];
            textEditingControllers.forEach((element) {
              test.add(element.text);
            });

            if(tcontroller == '' && dcontroller == '' && icontroller == ''){
              print("not valid");
            }else{
              var todo = Todo2(
                title: tcontroller.text,
                description: dcontroller.text,
                image: icontroller.text,
                tags: test,
              );
              updateData(todo, widget.docid.toString(),context);
              setState(() {
                showSnackBar(context, 'todo ${widget.doctitle} successfully updated!');
              });
            }
          },
          child: Icon(Icons.update),
    ),
    );
  }
}




Upvotes: 1

Views: 7602

Answers (2)

M&#228;ddin
M&#228;ddin

Reputation: 1327

You can't remove anything from the list with objects from tagForm(controller), because these objects are newly created and therefore not the same as in the list (as long as the == operator is not overwritten)

If you still want to have the widgets in a list instead of just storing the controllers and without having to change much, you could remove the widgets like this:

onPressed: (){
  setState(() {
    controller.dispose();
    textEditingControllers.remove(controller);
    textformFields.removeWhere((w) => w.controller = controller));
  });
},

and change the type of your List: var textformFields = <TextFormField>[]; and of the method TextFormField tagForm(controller).

In general, you can of course optimize the state management, but with this solution it should work for now.

Upvotes: 1

Tuan
Tuan

Reputation: 2421

Dont't store Widget, it is bad way. Insteads store there property, render by List then remove by index when you need.

ps: some code syntax can wrong, i write this on browser.

class _TodoEditState extends State<TodoEdit> {
  ...
  var textformFields = <String>[];
  ...
  void _addformWidget([String? initValue]) {
    setState(() => textformFields.add(initValue ?? ""));
  }
  ...
  Widget tagForm(String value, void Function(String) onChange, void Function() onRemove){
    var openEditor = () {
      // Open dialog with text field to edit from [value] call onChange with
      // new value
      OpenDialog().then((newvalue) {
        if(newvalue != null) onChange(newvalue);
      }
    };
    var delete = () {
      // Open confirm dialog then remove
      OpenConfirmDialog("your message").then((continue) {
        if(continue) onRemove();
      });
    };

    return InkWell(
      onTap: openEditor,
      child: Text(value), // render your tag value 
    );
  }
  ...
  @override
  void initState() {
    ...
    textformFields = List.filled(widget.doctags ?? 0, ""); // or List.generate/map if you want replace by own value.
  }
  ...
   @override
  Widget build(BuildContext context) {
    ...
    ListView.builder(
      itemCount: textformFields.length,
      itemBuilder: (context,index) => tagForm(
        textformFields[index],
        (newvalue) => setState(() => textformFields[index] = newvalue),
        () => setState(() => textformFields = textformFields..removeAt(index));,
      ),
    ),
    ...
  );
}

Upvotes: 1

Related Questions