HoiPolloi
HoiPolloi

Reputation: 379

Refresh dialog and parent from child/grandchild widget

I have a dialog with radio buttons that I want to refresh as the user taps on them and I want it to refresh the parent as well. Answers to similar questions suggest wrapping the contents of the dialog in a StatefulBuilder, but this is not working because the children of the dialog are these dialogOption widgets.

I've made a simple example:

class _MyHomePageState extends State<MyHomePage> {
  String selectedOption = "None";

  Widget dialogOption({@required String optionName}) {
    return InkWell(
      child: Row(children: [
        Icon(
          optionName == selectedOption
              ? Icons.radio_button_checked
              : Icons.radio_button_unchecked,
        ),
        Text(optionName),
      ]),
      onTap: () {
        setState(() {
          selectedOption = optionName;
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Text("Selected option: $selectedOption"),
          RaisedButton(
            child: Text("Open dialog"),
            onPressed: () {
              showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    return AlertDialog(
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          dialogOption(optionName: "Option 1"),
                          dialogOption(optionName: "Option 2"),
                        ],
                      ),
                    );
                  });
            },
          )
        ],
      ),
    );
  }
}

Tapping on dialogOption widgets above only refreshes the parent.

Now if I do it with StatefulBuilder like this:

return AlertDialog(
  content: StatefulBuilder(
    builder: (BuildContext context, StateSetter setState) {
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          // tapping will NOT refresh dialog
          dialogOption(optionName: "Option 1"), 
          // tapping will NOT refresh dialog
          dialogOption(optionName: "Option 2"),
          InkWell(
            child: Text("This will refresh dialog"),
            onTap: () { // this WILL refresh dialog
              setState(() {});
            },
          ),
        ],
      );
    },
  ),
);

tapping on two dialogOption widgets will not refresh the dialog but tapping on the Inkwell above will. I don't know what difference this makes but obviously I want those two options to refresh the dialog AND the parent.

Upvotes: 2

Views: 691

Answers (1)

CopsOnRoad
CopsOnRoad

Reputation: 267474

enter image description here

class _MyHomePageState extends State<MyHomePage> {
  String selectedOption = "None";

  Widget dialogOption({@required String optionName, @required Function refresh}) {
    return InkWell(
      child: Row(
        children: [
          Icon(
            optionName == selectedOption ? Icons.radio_button_checked : Icons.radio_button_unchecked,
          ),
          Text(optionName),
        ],
      ),
      onTap: () {
        refresh(() {
          setState(() {
            selectedOption = optionName;
          });
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Text("Selected option: $selectedOption"),
          RaisedButton(
            child: Text("Open dialog"),
            onPressed: () {
              showDialog(
                context: context,
                builder: (BuildContext context) {
                  return StatefulBuilder(
                    builder: (context, refresh) {
                      return AlertDialog(
                        content: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            dialogOption(optionName: "Option 1", refresh: refresh),
                            dialogOption(optionName: "Option 2", refresh: refresh),
                          ],
                        ),
                      );
                    },
                  );
                },
              );
            },
          )
        ],
      ),
    );
  }
}

Upvotes: 2

Related Questions