Home > Enterprise >  Delete Widget at button press Flutter
Delete Widget at button press Flutter

Time:04-06

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




CodePudding user response:

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));,
      ),
    ),
    ...
  );
}

CodePudding user response:

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.

  • Related