mardi 15 septembre 2020

Preserving Text in TextField in a Statefull Widget Flutter

I want to build a Multi Check Widget in my application, the problem that I am facing is that when I click on the delete button or try to add another option in the list the widget is redrawn and I lose the state and all the text fields are reset. There are parts in it when I enter title the text field does not reset because I am using TextEditingController, but when I use TextEditingControlle on options It does not work. How do I preserve the text in my options?

class MultiCheckBox extends StatefulWidget {
  final Function onDelete;
  final Function duplicate;
  final Icon prefixIcon;
  final String refText;
  final FormData data = FormData();
  TextEditingController _titleController = TextEditingController();
  TextEditingController _optionsController = TextEditingController();

  MultiCheckBox(Key key,
      {@required this.prefixIcon,
      @required this.refText,
      @required this.duplicate,
      @required this.onDelete})
      : super(key: key);

  @override
  _MultiCheckBoxState createState() => _MultiCheckBoxState();
}

class _MultiCheckBoxState extends State<MultiCheckBox> {

  List<Map<String, dynamic>> _options = [
    {
      'name': 'option 1',
      'key': UniqueKey(),
      'controller': TextEditingController()
    },
    {
      'name': 'option 2',
      'key': UniqueKey(),
      'controller': TextEditingController()
    }
  ];

  void addOptions() {
    setState(() {
      _options.add({
        'key': UniqueKey(),
        'name': "option ${_options.length + 1}",
        'controller': TextEditingController()
      });
    });
  }

  List<Widget> _buildOptionsList() {
    List<Widget> list = [];
    _options.asMap().forEach((index, value) {
      list.add(_buildOptionsField(index, value, TextEditingController()));
    });
    return list;
  }

  Widget _buildOptionsField(int index, Map<String, dynamic> option,
      TextEditingController controller) {
    return Padding(
      key: option['key'],
      padding: EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
      child: TextField(
        controller: controller,
//        initialValue: options,
        keyboardType: TextInputType.text,
        textInputAction: TextInputAction.next,
        decoration: InputDecoration(
          prefixIcon: IconButton(
            onPressed: () {},
            icon: widget.prefixIcon,
          ),
          suffixIcon: IconButton(
            onPressed: () {
              setState(() {
                print("deleting at index $index");
                _options.remove(option);
              });
            },
            icon: Icon(Icons.close),
          ),
          hintText: option['name'],
          hintStyle: TextStyle(
            color: Colors.grey,
            fontStyle: FontStyle.italic,
            fontSize: 14.0,
          ),
        ),
        onSubmitted: (text) {},
        onChanged: (v) {
//          _options.insert(index, v);
        },
      ),
    );
  }

  void deleteWidget(index) {
    setState(() {
      this
          .widget
          .data
          .widgets
          .removeWhere((element) => element.key == Key('index_$index'));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(bottom: 12.0),
      decoration: BoxDecoration(
        color: Colors.amber.shade400,
        borderRadius: BorderRadius.only(
          topRight: Radius.circular(15.0),
          topLeft: Radius.circular(15.0),
        ),
      ),
      child: Column(
        children: <Widget>[
          Padding(
            padding: EdgeInsets.all(6.0),
            child: Text(
              widget.refText,
              style: TextStyle(
                color: Colors.white,
                fontSize: 18.0,
              ),
            ),
          ),
          Card(
            elevation: 5.0,
            color: Colors.amber.shade50,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(15.0),
                topRight: Radius.circular(15.0),
              ),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
                  child: TextField(
                    controller: widget._titleController,
                    keyboardType: TextInputType.text,
                    textInputAction: TextInputAction.next,
                    decoration: InputDecoration(
                      hintText: 'enter field name',
                      hintStyle: TextStyle(
                        color: Colors.grey,
                        fontStyle: FontStyle.italic,
                        fontSize: 14.0,
                      ),
                    ),
                    onSubmitted: (_) => FocusScope.of(context).nextFocus(),
                  ),
                ),
                ..._buildOptionsList(),
                Align(
                  alignment: Alignment.centerRight,
                  child: FlatButton(
                    onPressed: addOptions,
                    child: Text(
                      'Add Option',
                      style: TextStyle(color: Theme.of(context).primaryColor),
                    ),
                  ),
                ),
                Divider(
                  indent: 4.0,
                  endIndent: 4.0,
                  thickness: 2.0,
                ),
                IntrinsicHeight(
                    child: FormFieldControl(
                  onDelete: widget.onDelete,
                  onDuplicate: widget.duplicate,
                )),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

My titleController works and it is preserving the text, but below the when options are entered and Add Options is clicked the text entered in options resets. see image for reference. enter image description here
Please help how I do save the text when entered in options. Thank you !




Aucun commentaire:

Enregistrer un commentaire