Flutter textFiled input is always save the change in AlertDialog widget

45 Views Asked by At

I have problem that create cancel button in textField.

But it's always save changing cancel button and submit button both

If I delete the cancel button code, it's also save the change of textField when pop alertdialog by clicking background

I find some video and document but there is not different in code

https://www.youtube.com/watch?v=TpW7nLL57uQ

Below: My AlertDialog code

Future<void> editField(String field) async {
    String newValue = '';
    await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        backgroundColor: Colors.grey[100],
        title: Text(
          "Edit $field",
          style: const TextStyle(color: Colors.black),
        ),
        content: TextField(
          autofocus: true,
          style: const TextStyle(color: Colors.black),
          decoration: InputDecoration(
            hintText: "Enter new $field",
            hintStyle: const TextStyle(color: Colors.grey),
          ),
          onChanged: (value) {
            newValue = value;
          },
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Cancel'),
          ),
          TextButton(
            onPressed: () => Navigator.of(context).pop(newValue),
            child: const Text('Submit'),
          ),
        ],
      ),
    );
    if (newValue.trim().isNotEmpty) {
      await userCollection.doc(currentUser.email).update({field: newValue});
    }
  }
2

There are 2 best solutions below

1
manhtuan21 On BEST ANSWER

Your code make newValue is a global value, it will change on this callback

onChanged: (value) {
   newValue = value;
},

no matter what you pop from Dialog. So you should use a local value dialogValue in Dialog and pop it when you press Submit button

showDialog is a Future function that return result after you

Navigator.pop(context, result) in Dialog. Example:

final result = await showDialog(...);

or

var result;
showDialog(...).then((value) {
   result = value;
});

two ways above is the same.

Try this code:

  Future<void> editField(String field) async {
    String newValue = '';
    
    await showDialog(
      context: context,
      builder: (context) {
        String dialogValue = '';
        return AlertDialog(
          backgroundColor: Colors.grey[100],
          title: Text(
            "Edit $field",
            style: const TextStyle(color: Colors.black),
          ),
          content: TextField(
            autofocus: true,
            style: const TextStyle(color: Colors.black),
            decoration: InputDecoration(
              hintText: "Enter new $field",
              hintStyle: const TextStyle(color: Colors.grey),
            ),
            onChanged: (value) {
              dialogValue = value;
            },
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('Cancel'),
            ),
            TextButton(
              onPressed: () => Navigator.of(context).pop(dialogValue),
              child: const Text('Submit'),
            ),
          ],
        );
      },
    ).then((value) {
      newValue = value;
    });
    
    if (newValue.trim().isNotEmpty) {
      await userCollection.doc(currentUser.email).update({field: newValue});
    }
  }
0
SRB Bans On

Put this code in on submit as this is being executed in either condition.

  if (newValue.trim().isNotEmpty) {
     await userCollection.doc(currentUser.email).update({field: newValue});
  }