1

I am new to flutter) I want to make function which calls showDialog() with 2 TextField() when user press the FloatingActionButton() in the main.dart file.

I don't know how to call a function in a main file Stateful Widget from another StatefulWidget (from another file called VVid.dart)

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  String cardText = '';

  void updateCardText(String text) {
    setState(() {
      cardText = text;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Transaction App'),
        ),
        body: Container(
          color: Colors.amber,
          height: 200,
          width: 300,
          child: Card(
            child: Text(cardText),
          ),
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              // Forma.showTextField(context);
            });
          },
          child: Icon(Icons.add),
        ));
  }
}

// vvid.dart //////////////////////////////////////

class Forma extends StatefulWidget {
  @override
  State<Forma> createState() => FormaState();
}

class FormaState extends State<Forma> {
  final vvidText = TextEditingController();

  final vvidAmount = TextEditingController();

  void showTextField(BuildContext context) {
    showDialog(
      context: context,
      builder: ((context) {
        return AlertDialog(
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                controller: vvidText,
                decoration: const InputDecoration(
                    hintText: "Title",
                    hintStyle: TextStyle(color: Colors.grey)),
              ),
              TextField(
                controller: vvidAmount,
                decoration: const InputDecoration(
                    hintText: "Amount",
                    hintStyle: TextStyle(color: Colors.grey)),
                keyboardType: TextInputType.number,
              ),
            ],
          ),
          title: Text('My Transaction'),
          actions: [
            Row(
              children: [
                TextButton(
                    onPressed: (() {
                      Navigator.of(context).pop();
                    }),
                    child: Text('Ok')),
                TextButton(
                    onPressed: (() {
                      Navigator.pop(context, vvidText.text);
                    }),
                    child: Text('Close')),
              ],
            ),
          ],
        );
      }),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
Eliza_K
  • 13
  • 2
  • Cant find the place you've use `Forma`widget on `MyHomePage`. is it just for dialog? – Md. Yeasin Sheikh Mar 17 '23 at 10:06
  • The idea is to make that when user click on the flatActionButto, the dialog window with TextFields opens and after the user clicks "Ok" button, a Card widget with what the user has entered should appear on the screen – Eliza_K Mar 17 '23 at 10:20

2 Answers2

0

You could rewrite your Forma class like this:

class Forma extends StatefulWidget {
  @override
  State<Forma> createState() => FormaState();

  static Future<String?> showTextField(BuildContext context) async {
    return await showDialog(
      context: context,
      builder: ((context) {
        return Forma();
      }),
    );
  }
}

class FormaState extends State<Forma> {
  final vvidText = TextEditingController();

  final vvidAmount = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          TextField(
            controller: vvidText,
            decoration: const InputDecoration(
                hintText: "Title",
                hintStyle: TextStyle(color: Colors.grey)),
          ),
          TextField(
            controller: vvidAmount,
            decoration: const InputDecoration(
                hintText: "Amount",
                hintStyle: TextStyle(color: Colors.grey)),
            keyboardType: TextInputType.number,
          ),
        ],
      ),
      title: Text('My Transaction'),
      actions: [
        Row(
          children: [
            TextButton(
                onPressed: (() {
                  Navigator.of(context).pop();
                }),
                child: Text('Ok')),
            TextButton(
                onPressed: (() {
                  Navigator.pop(context, vvidText.text);
                }),
                child: Text('Close')),
          ],
        ),
      ],
    );
  }
}

And let this be the onPressed:

          onPressed: () {
            Forma.showTextField(context).then((value) => setState(() {
                  cardText = value ?? '';
                }));
          },

You will see the vvidText will be passed if you press the close button

Ivo
  • 18,659
  • 2
  • 23
  • 35
  • The idea is to make that when user click on the flatActionButto, the dialog window with TextFields opens and after the user clicks "Ok" button, a Card widget with what the user has entered should appear on the screen – Eliza_K Mar 17 '23 at 10:25
  • @Eliza_K I've edited the answer. Please try it – Ivo Mar 17 '23 at 10:38
0

you don't need your Forma class, just extract the dialog method into your main class, and make it return the values from your controllers, then use that value to update your card:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  String cardText = '';

  void updateCardText(String text) {
    setState(() {
      cardText = text;
    });
  }

  Future<String?> showTextField(BuildContext context) {
    final vvidText = TextEditingController();
    final vvidAmount = TextEditingController();

    return showDialog<String?>(
      context: context,
      builder: ((context) {
        return AlertDialog(
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                controller: vvidText,
                decoration: const InputDecoration(hintText: "Title", hintStyle: TextStyle(color: Colors.grey)),
              ),
              TextField(
                controller: vvidAmount,
                decoration: const InputDecoration(hintText: "Amount", hintStyle: TextStyle(color: Colors.grey)),
                keyboardType: TextInputType.number,
              ),
            ],
          ),
          title: const Text('My Transaction'),
          actions: [
            Row(
              children: [
                TextButton(
                    onPressed: (() {
                      Navigator.of(context).pop();
                    }),
                    child: const Text('Ok')),
                TextButton(
                    onPressed: (() {
                      Navigator.pop(context, vvidText.text);
                    }),
                    child: const Text('Close')),
              ],
            ),
          ],
        );
      }),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Transaction App'),
        ),
        body: Container(
          color: Colors.amber,
          height: 200,
          width: 300,
          child: Card(
            child: Text(cardText),
          ),
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            showTextField(context).then((value) {
              if (value != null) {
                updateCardText(value);
              }
            });
          },
          child: const Icon(Icons.add),
        ));
  }
}

you can even return from your showDialog method a List<String>? if you want to return the value from both textFields

AJ-
  • 1,638
  • 1
  • 24
  • 49
  • The idea is to make that when user click on the flatActionButto, the dialog window with TextFields opens and after the user clicks "Ok" button, a Card widget with what the user has entered should appear on the screen – Eliza_K Mar 17 '23 at 10:25
  • @Eliza_K I updated my answer with what you want to achieve – AJ- Mar 17 '23 at 10:39