DEV Community

Cover image for How To Add States Functionality Inside Flutter showDialog() Function
Almatin Siswanto
Almatin Siswanto

Posted on

How To Add States Functionality Inside Flutter showDialog() Function

When I add a CheckBox() widget inside the content of the AlertDialog widget inside of the showDialog() function in the TextButton widget onPressed() function, I found that the checkbox did not rebuild when I click on it.

The checkbox did not rebuild because the showDialog() has its own build context. Even when I am using the StatefulWidget, the checkbox did not response and rebuild as expected when I click on it.

So, I wrap the AlertDialog widget using a StatefulBuilder widget and move the Boolean variable for the checkbox value above it and it solved the checkbox issue.

Here are the steps:

Before

import 'package:flutter/material.dart';

import '../../constants/colors.dart';
import '../../constants/styles.dart';

class DialogSendFeedback extends StatefulWidget {
  const DialogSendFeedback({super.key});

  @override
  State<DialogSendFeedback> createState() => _DialogSendFeedbackState();
}

class _DialogSendFeedbackState extends State<DialogSendFeedback> {
  final TextEditingController feedback = TextEditingController();
  final FocusNode feedbackFocus = FocusNode();

  bool agree = false;

  @override
  void dispose() {
    feedback.dispose();
    feedbackFocus.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextButton.icon(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) {
              return AlertDialog(
                title: const Text('Send the project to Engineers'),
                content: SizedBox(
                  width: 600,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Row(
                        children: [
                          Expanded(
                              child: Text(
                            'We are sorry that you encountered some issues. To assist us in investigating the matter, kindly provide the details of the project.',
                            maxLines: 3,
                          ))
                        ],
                      ),
                      const SizedBox(
                        height: 16,
                      ),
                      Expanded(
                        child: Row(
                          children: [
                            Expanded(
                                child: TextFormField(
                              controller: feedback,
                              focusNode: feedbackFocus,
                              autofocus: true,
                              keyboardType: TextInputType.multiline,
                              textInputAction: TextInputAction.newline,
                              maxLines: 100,
                              decoration: const InputDecoration(
                                  alignLabelWithHint: true,
                                  contentPadding: EdgeInsets.all(8),
                                  label: Text('Issue detail'),
                                  hintText:
                                      'Describe the issue as detailed as possible.'),
                            ))
                          ],
                        ),
                      ),
                      const SizedBox(
                        height: 16,
                      ),
                      Row(
                        children: [
                          Checkbox(
                              checkColor: whiteColor,
                              fillColor: WidgetStateProperty.resolveWith(
                                  (states) => darkTealColor),
                              value: agree,
                              onChanged: (bool? value) {
                                setState(() {
                                  agree = value!;
                                });
                              }),
                          const SizedBox(
                            width: 8,
                          ),
                          const Expanded(
                            child: Text(
                              'I agree to send these project details to Schletter Engineering for their investigation.',
                              maxLines: 3,
                            ),
                          )
                        ],
                      )
                    ],
                  ),
                ),
                actions: [
                  TextButton(
                      style: defaultPrimaryButtonStyle,
                      onPressed: () {
                        Navigator.of(context).pop(false);
                      },
                      child: const Text(
                        'Do not send',
                        style: buttonTextWhite,
                      )),
                  TextButton(
                      style: defaultSecondaryButtonStyle,
                      onPressed: agree == true
                          ? () {
                              Navigator.of(context).pop(true);
                            }
                          : null,
                      child: Text(
                        'Send',
                        style: defaultSecondaryButtonTextStyle,
                      ))
                ],
              );
            },
          ).then((value) {
            if (value == true) {
              // make a call to backend API to save the feedback
            }
          });
        },
        icon: const Icon(
          Icons.help_outline_rounded,
          color: whiteColor,
        ),
        label: Text(
          'Ask for help',
          style: defaultPrimaryButtonTextStyle,
        ));
  }
}
Enter fullscreen mode Exit fullscreen mode

After

import 'package:flutter/material.dart';

import '../../constants/colors.dart';
import '../../constants/styles.dart';

class DialogSendFeedback extends StatefulWidget {
  const DialogSendFeedback({super.key});

  @override
  State<DialogSendFeedback> createState() => _DialogSendFeedbackState();
}

class _DialogSendFeedbackState extends State<DialogSendFeedback> {
  final TextEditingController feedback = TextEditingController();
  final FocusNode feedbackFocus = FocusNode();

  @override
  void dispose() {
    feedback.dispose();
    feedbackFocus.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextButton.icon(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) {
              bool agree = false; // <- here
              return StatefulBuilder( // <- here
                builder: (context, setState) => AlertDialog(
                  title: const Text('Send the project to Engineers'),
                  content: SizedBox(
                    width: 600,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        const Row(
                          children: [
                            Expanded(
                                child: Text(
                              'We are sorry that you encountered some issues. To assist us in investigating the matter, kindly provide the details of the project.',
                              maxLines: 3,
                            ))
                          ],
                        ),
                        const SizedBox(
                          height: 16,
                        ),
                        Expanded(
                          child: Row(
                            children: [
                              Expanded(
                                  child: TextFormField(
                                controller: feedback,
                                focusNode: feedbackFocus,
                                autofocus: true,
                                keyboardType: TextInputType.multiline,
                                textInputAction: TextInputAction.newline,
                                maxLines: 100,
                                decoration: const InputDecoration(
                                    alignLabelWithHint: true,
                                    contentPadding: EdgeInsets.all(8),
                                    label: Text('Issue detail'),
                                    hintText:
                                        'Describe the issue as detailed as possible.'),
                              ))
                            ],
                          ),
                        ),
                        const SizedBox(
                          height: 16,
                        ),
                        Row(
                          children: [
                            Checkbox(
                                checkColor: whiteColor,
                                fillColor: WidgetStateProperty.resolveWith(
                                    (states) => darkTealColor),
                                value: agree,
                                onChanged: (bool? value) {
                                  setState(() {
                                    agree = value!;
                                  });
                                }),
                            const SizedBox(
                              width: 8,
                            ),
                            const Expanded(
                              child: Text(
                                'I agree to send these project details to Schletter Engineering for their investigation.',
                                maxLines: 3,
                              ),
                            )
                          ],
                        )
                      ],
                    ),
                  ),
                  actions: [
                    TextButton(
                        style: defaultPrimaryButtonStyle,
                        onPressed: () {
                          Navigator.of(context).pop(false);
                        },
                        child: const Text(
                          'Do not send',
                          style: buttonTextWhite,
                        )),
                    TextButton(
                        style: defaultSecondaryButtonStyle,
                        onPressed: agree == true
                            ? () {
                                Navigator.of(context).pop(true);
                              }
                            : null,
                        child: Text(
                          'Send',
                          style: defaultSecondaryButtonTextStyle,
                        ))
                  ],
                ),
              );
            },
          ).then((value) {
            if (value == true) {
              // make a call to backend API to save the feedback
            }
          });
        },
        icon: const Icon(
          Icons.help_outline_rounded,
          color: whiteColor,
        ),
        label: Text(
          'Ask for help',
          style: defaultPrimaryButtonTextStyle,
        ));
  }
}
Enter fullscreen mode Exit fullscreen mode

That’s it. Hopefully you found this post useful. Happy coding!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up