Search code examples
flutterdartstatefulstatefulwidget

How to call a function in a main file Stateful Widget from another StatefulWidget in another file?


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();
  }
}


Solution

  • 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