How to call flutter dialog from separate class?

Viewed 828

I need to separate my dialog to separate widgets an call from anywhere on some button click. Now my code looks like:

import 'package:flutter/material.dart';

class PlacesListScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _Map();
  }
}

class _Map extends StatefulWidget {
  @override
  _MapState createState() => _MapState();
}

class _MapState extends State<_Map> {

  final _titleController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App name'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
              return showDialog(
                context: context,
                builder: (ctx) => AlertDialog(
                  title: Text(
                    "Dialog title",
                    textAlign: TextAlign.center,
                  ),
                  content: TextField(
                    decoration: InputDecoration(labelText: 'Title'),
                    controller: _titleController,
                  ),
                  actions: <Widget>[
                    FlatButton(
                      onPressed: () {
                        Navigator.of(ctx).pop();
                      },
                      child: Text("No"),
                    ),
                    FlatButton(
                      onPressed: () {
                        return showDialog(
                          context: context,
                          builder: (ctx) => StatefulBuilder(builder:
                              (BuildContext context, StateSetter setState) {
                            return AlertDialog(
                              title: Text(
                                "Second subdialog title",
                                textAlign: TextAlign.center,
                              ),
                              content: Container(
                                width: 150,
                                height: 200,
                                decoration: BoxDecoration(
                                  border:
                                      Border.all(width: 1, color: Colors.grey),
                                ),
                                child: Text('Here will be file'),
                                alignment: Alignment.center,
                              ),
                              actions: <Widget>[
                                FlatButton(
                                  onPressed: () {
                                    Navigator.of(ctx).pop();
                                  },
                                  child: Text("No"),
                                ),
                                FlatButton(
                                  onPressed: () => Text('Here I will work with state'),
                                  child: Text("Yes"),
                                ),
                              ],
                            );
                          }),
                        );
                      },
                      child: Text("Yes"),
                    ),
                  ],
                ),
              );
            },
          ),
        ],
      ),
      body: Text('App body here'),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          FloatingActionButton(
            onPressed: () => Text('Here will be called dialog function'),
            child: Icon(Icons.add, color: Colors.white),
            backgroundColor: Colors.green,
            heroTag: 'mapZoomIn',
          ),
        ],
      ),
    );
  }
}

Now how I can this part of code (calling dialog) separate to another widget and call then using created widget.

showDialog(
  context: context,
  builder: (ctx) => StatefulBuilder(builder:
      (BuildContext context, StateSetter setState) {
    return AlertDialog(
      title: Text(
        "Second subdialog title",
        textAlign: TextAlign.center,
      ),
      content: Container(
        width: 150,
        height: 200,
        decoration: BoxDecoration(
          border:
              Border.all(width: 1, color: Colors.grey),
        ),
        child: Text('Here will be file'),
        alignment: Alignment.center,
      ),
      actions: <Widget>[
        FlatButton(
          onPressed: () {
            Navigator.of(ctx).pop();
          },
          child: Text("No"),
        ),
        FlatButton(
          onPressed: () => Text('Here I will work with state'),
          child: Text("Yes"),
        ),
      ],
    );
  }),
);
3 Answers

Firstly, you can refactor your StatefulBuilder(builder: (BuildContext context, StateSetter setState) { return AlertDialog(... into one separate widget like MyFancyDialog extends StatefulWidget. Then just call showDialog(..., MyFancyWidget()) when you need it.

Secondly, if you do not want the first method, you can extract the whole showDialog(...) into a function like void showMyFancyDialog() { showDialog... }. Is it also OK, since in dart functions are first class.

Did you try to create a new Stateful widget class at the bottom of your code and try to call that widget? If you didn't try that,

  1. Go to under of your code and create a new Stateful class. (Let's say that myDialog)
  2. Add the code that you want to call, inside of your "myDialog" widget
  3. Go for where you want to call that code and try to call that class.

Hope this works for you.

  1. Create a separate file. Import material package.
  2. then create "Widget myDialog(context){ // paste your showDialog code here }"
  3. Now your myDialog widget has been ready for using anywhere on whole project just import and call it.
  4. When you call it pass BuildContext in its argument.

Its work for me.

Related