showDialog bug: dialog isn't triggered from PopupMenuButton in Flutter

424

Solution 1

It's not a bug. As I remember, the "onTap" callback of PopupMenuItem calls Navigator.pop to close the Popup. In that case, when you tap on the PopupMenuItem and call "showDialog", the dialog will be popped immediately, and leaves the Popup open.

In order to overcome that, you may try this solution :

PopupMenuItem(
             child: const Text('Alert'),
              onTap: () {
                Future.delayed(
                    const Duration(seconds: 0),
                    () => showDialog(
                          context: context,
                          builder: (context) => const AlertDialog(
                            title: Text('test dialog'),
                          ),
                        ));
              },
            )

Solution 2

There is an easier way to achieve it using the actual functionality of PopupMenuButton.

Just give a value to you PopUpMenuItem and check for it on the onSelected callback from PopupMenuButton as follows:

PopupMenuButton<String>(
  onSelected: (value) async {
    switch (value) {
      case 'open_dialog':
        return showDialog(...);
      default:
        throw UnimplementedError();
    }
  },
  itemBuilder: (context) => [
    const PopupMenuItem(
      child: Text('Open dialog'),
      value: 'open_dialog',
    ),
  ],
),

This way you will consume the parent context and not the itemBuilder context that gets popped on tap as mentioned here. Then decide what to execute when that value is received, for example, opening the dialog.

You can also use an enum instead of String as values if you want to have it properly type safe.

Share:
424
kamalbanga
Author by

kamalbanga

Data Scientist at Myntra

Updated on December 06, 2022

Comments

  • kamalbanga
    kamalbanga over 1 year

    I am not able to get showDialog work with PopupMenuButton. In the example below, there is a button with triggering a dialog to display and a popupmenu too triggering a dialog to display.

    The button works but on clicking on the Alert text in PopupMenu, the same doesn't happen.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('showDialog bug'), actions: [
              PopupMenuButton(
                  itemBuilder: (ctx) => [
                        PopupMenuItem(
                            child: Text('Alert'),
                            onTap: () {
                              showDialog(
                                  context: context,
                                  builder: (ctx) => AlertDialog(
                                        title: Text('test dialog'),
                                      ));
                            })
                      ])
            ]),
            body: ElevatedButton(
                onPressed: () {
                  showDialog(
                      context: context,
                      builder: (ctx) => AlertDialog(
                            title: Text('test dialog'),
                          ));
                },
                child: Text('click me')));
      }
    }
    

    However, when I add another block of showDialog subsequent to it, it starts working.

    showDialog(
    context: context,
    builder: (ctx) => AlertDialog(
          title: Text('test dialog'),
        ));