Setstate() not working to update suffixIcon inside AlertDialog ? – Flutter

Issue

I’m trying to update the suffixIcon in Form for TextFormField’s InputDecoration , to check the length of the giving String by onChange function ,but no update . In add I did test on Textcontroller to give it value when the length >= 8 it’s worked ,I wish I give a good idea for the issue . thanks in advance for your solution .

import 'package:flutter/material.dart';

bulidDialogChangePass() {
  return DialogPass();
}

class DialogPass extends StatefulWidget {
  const DialogPass({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return DialogPassState();
  }
}

class DialogPassState extends State<DialogPass> {
  TextEditingController _fPasswordValue = TextEditingController();
  TextEditingController _sPasswordValue = TextEditingController();
  final _formKey = GlobalKey<FormState>();
  ValueChanged<String>? onChanged;
  bool _showIcons = false;
  bool _startValidateFPass = false;
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 25.0),
      child: Wrap(
        children: [
          Container(
            child: Row(
              children: [
                Text("Password :"),
                TextButton(
                  onPressed: () {
                    _showDialog(context);
                  },
                  child: Wrap(
                    direction: Axis.vertical,
                    alignment: WrapAlignment.end,
                    children: [Text("Change")],
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    );
  }

  _showDialog(BuildContext context) async {
    var size = MediaQuery.of(context).size;
    return await showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            content: Stack(
              clipBehavior: Clip.none,
              children: <Widget>[
                Form(
                  key: _formKey,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.all(8.0),
                        child: TextFormField(
                          controller: _fPasswordValue,
                          onChanged: (value) {_onChange(_fPasswordValue.text);},
                          decoration: InputDecoration(
                            labelText: "New Password",
                            suffixIcon: _showIcons && _startValidateFPass ?  _setIcon() :null,
                          ),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.all(8.0),
                        child: TextFormField(
                          controller: _sPasswordValue,
                          decoration: InputDecoration(
                            labelText: "Confirm Password",
                            suffixIcon: _showIcons && _startValidateFPass ?  _setIcon() :null, // I will change to check aothers soon 
                          ),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Wrap(
                          children: [
                            OutlinedButton(
                              style: OutlinedButton.styleFrom(
                                fixedSize: Size(size.width / 2 - 10, 20),
                                padding: EdgeInsets.symmetric(horizontal: 50),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(20)),
                              ),
                              onPressed: () {},
                              child: Text("CANCEL",
                                  style: TextStyle(
                                      fontSize: 14,
                                      letterSpacing: 2.2,
                                      color: Colors.black)),
                            ),
                            OutlinedButton(
                              style: OutlinedButton.styleFrom(
                                fixedSize: Size(size.width / 2 - 10, 20),
                                backgroundColor: Colors.blue[400],
                                primary: Colors.black,
                                padding: EdgeInsets.symmetric(horizontal: 50),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(20)),
                              ),
                              onPressed: () {},
                              child: Text("Save",
                                  style: TextStyle(
                                      fontSize: 14,
                                      letterSpacing: 2.2,
                                      color: Colors.black)),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          );
        });
  }

  _onChange(String value) {
    setState(() {
      _startValidateFPass = true;
      if (value.length >= 8) {
        _sPasswordValue.text = "test"; // test to check setState
        _showIcons = true;
      }
    });
  }
  Icon _setIcon() {
    Icon icon;
    if(_showIcons){
      _sPasswordValue.text = "test"; // test to check setState
      print('dfsdfsd');
      icon = Icon(
        Icons.done_all,
        color: Colors.green,
      );
    }else{
      icon = Icon(
        Icons.highlight_off,
        color: Colors.red,
      );
    }
    return icon;
  }
}

Solution

Make another stateful widget and make Alertdialog as its child or use stateful builder to accomplish this as

    showDialog(
  context: context,
  builder: (context) {
    String contentText = "Your Dialog";
    return StatefulBuilder(
      builder: (context, setState) {
        return AlertDialog(
          title: Text("Title"),
          content: Text(contentText),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text("Cancel"),
            ),
            TextButton(
              onPressed: () {
                setState(() {
                  contentText = "Changed state";
                });
              },
              child: Text("Change"),
            ),
          ],
        );
      },
    );
  },
);

Answered By – sid

Answer Checked By – Robin (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.