skip to Main Content

Is Any Way How to pass a widget function to another page that is without any stateless/stateful? The file only includes widgets such as textfields, buttons and etc. I am trying not to cluster every fields in one page. Any helps/ideas would be appreciated!

Main.dart

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<Main Page> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
// bool for toggling password
  bool isSecuredPasswordField = true;
  @override
  Widget build(BuildContext context) {
    return Container();
  }
// widget function that I need to pass on widget_fields.dart
 Widget togglePassword() {
    return IconButton(
      onPressed: () {
        setState(() {
          isSecuredPasswordField = !isSecuredPasswordField;
        });
      },
      icon: isSecuredPasswordField
          ? const Icon(Icons.visibility)
          : const Icon(Icons.visibility_off),
    );
  }
}

widget_fields.dart

Widget userPasswordField(_passwordUserCtrlr) {
  return Padding(
    padding: const EdgeInsets.symmetric(horizontal: 25.0),
    child: TextFormField(
      obscureText: true,
      controller: _passwordUserCtrlr,
      keyboardType: TextInputType.visiblePassword,
      decoration: InputDecoration(
        isDense: true,
        suffixIcon: togglePassword(), //<-- I wanna call that function here
        prefixIcon: const Icon(Icons.lock),
        enabledBorder: OutlineInputBorder(
          borderSide: const BorderSide(color: Color(0xFFCECECE)),
          borderRadius: BorderRadius.circular(12),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: const BorderSide(color: Color(0xFFCECECE)),
        ),
        hintText: 'Password',
        hintStyle: const TextStyle(
          fontFamily: 'Poppins',
          fontSize: 14,
        ),
        fillColor: const Color(0xFFFEFEFE),
        filled: true,
      ),
      validator: (value) {
        if (value!.isEmpty) {
          return "Please enter your password.";
        } else if (value.length < 8) {
          return "Password should be min. 8 characters.";
        } else {
          return null;
        }
      },
    ),
  );
}

5

Answers


  1. What you are trying to do is impossible in the Flutter framework. You cannot call methods belonging to other widgets

    Also, it is discouraged to use function to return widgets as this impacts the framework’s ability to optimize the build process.

    One possible solution is to package your complete password entry in a set of custom (statefull) widgets. You can collect those into a single source file if you like. Be sure to create a class for every widget.

    Login or Signup to reply.
  2. This is Example that how you call Widget in another class:

      class MainApge extends StatefulWidget {
      const MainApge({Key? key}) : super(key: key);
    
      @override
      State<MainApge> createState() => _MainApgeState();
    }
    
    class _MainApgeState extends State<MainApge> {
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            ContainerTextFields.customsTextField(
              "User Name",
              'enter name',
              userNameController,
            ),
          ],
        );
      }
    }
    

    This is Custom Widget Class:

     class ContainerTextFields {
          static Widget customsTextField(
              String label, String cusHintText, TextEditingController _controller) {
            return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
              Padding(
                  padding: EdgeInsets.only(
                      left: SizeConfig.screenHeight! * 0.05,
                      top: SizeConfig.screenHeight! * 0.03),
                  child: Text(
                    label,
                    style: AppStyle.kUnSyncedDialogeText.copyWith(
                        color: AppColors.kTextFieldLabelColorGrey,
                        fontWeight: FontWeight.bold),
                  )),
              Padding(
                padding: EdgeInsets.only(
                    top: SizeConfig.screenHeight! * 0.02,
                    left: SizeConfig.screenHeight! * 0.042,
                    right: SizeConfig.screenWidth! * 0.042),
                child: SingleChildScrollView(
                  child: Container(
                    height: SizeConfig.screenHeight! * 0.065,
                    child: TextFormField(
                      controller: _controller,
                      decoration: InputDecoration(
                        hintText: cusHintText,
                        hintStyle: TextStyle(
                          color: AppColors.kLoginPopUpColor,
                        ),
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                        ),
                      ),
                    ),
                  ),
                ),
              )
            ]);
          }
        }
    
    Login or Signup to reply.
  3. You can create class like GlobalWidget for example, like this:

    class GlobalWidget {
    
     // widget function that I need to pass on widget_fields.dart
     Widget togglePassword(Function()? onPressed, bool value) {
        return IconButton(
          onPressed: onPressed,
          icon: value
              ? const Icon(Icons.visibility)
              : const Icon(Icons.visibility_off),
        );
      }
    
    }
    

    And You can call the Widget like that :

    GlobalWidget().togglePassword(() => setState(() {
        isSecuredPasswordField = !isSecuredPasswordField;
      }), isSecuredPasswordField)
    
    Login or Signup to reply.
  4. You can pass functions like any other variable. I made a full working example that’s different than yours to show a more minimal example but you can apply the same logic for your code

    main.dart

    import 'package:flutter/material.dart';
    
    import 'column.dart';
    
    void main() {
      runApp(const MaterialApp(home: MyApp()));
    }
    
    class MyApp extends StatefulWidget {
      const MyApp({super.key});
    
      @override
      MyAppState createState() => MyAppState();
    }
    
    class MyAppState extends State<MyApp> {
      Widget returnSomeText() {
        return const Text("test");
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(body: createColumn(returnSomeText));
      }
    }
    

    column.dart

    import 'package:flutter/material.dart';
    
    Widget createColumn(Function widgetFunction) {
      return Column(
        children: [widgetFunction(), widgetFunction()],
      );
    }
    

    As you can see the togglePassword from your code corresponds to returnSomeText in mine. and userPasswordField is like createColumn. But it must be said that it’s not recommended to use helper functions like createColumn here but to turn it into a StatelessWidget, like this for example:

    import 'package:flutter/material.dart';
    
    class CreateColumn extends StatelessWidget {
      final Function widgetFunction;
      const CreateColumn({Key? key, required this.widgetFunction}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [widgetFunction(), widgetFunction()],
        );
      }
    }
    

    And then in main.dart:

    return Scaffold(body: CreateColumn(widgetFunction: returnSomeText));
    

    See also this YouTube video: Widgets vs helper methods

    Login or Signup to reply.
  5. You can pass the widget as parameter to child widget:

    class MyTextField extends StatelessWidget {
      const MyTextField({Key? key,
        this.togglePassword,
        this.passwordUserCtrlr
      })
          : super(key: key);
    
      final Widget? togglePassword;
      final TextEditingController? passwordUserCtrlr;
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 25.0),
          child: TextFormField(
            obscureText: true,
            controller: passwordUserCtrlr,
            keyboardType: TextInputType.visiblePassword,
            decoration: InputDecoration(
              isDense: true,
              suffixIcon: togglePassword, //<-- I wanna call that function here
              prefixIcon: const Icon(Icons.lock),
              enabledBorder: OutlineInputBorder(
                borderSide: const BorderSide(color: Color(0xFFCECECE)),
                borderRadius: BorderRadius.circular(12),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(12),
                borderSide: const BorderSide(color: Color(0xFFCECECE)),
              ),
              hintText: 'Password',
              hintStyle: const TextStyle(
                fontFamily: 'Poppins',
                fontSize: 14,
              ),
              fillColor: const Color(0xFFFEFEFE),
              filled: true,
            ),
            validator: (value) {
              if (value!.isEmpty) {
                return "Please enter your password.";
              } else if (value.length < 8) {
                return "Password should be min. 8 characters.";
              } else {
                return null;
              }
            },
          ),
        );
      }
    }
    

    And can easily call from main widget:

    class MainPage extends StatefulWidget {
      const MainPage({super.key});
    
      @override
      State<MainPage> createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
    // bool for toggling password
      bool isSecuredPasswordField = true;
      TextEditingController? passwordUserCtrlr = TextEditingController();
      @override
      Widget build(BuildContext context) {
        return MyTextField(
          togglePassword: togglePassword(),
          passwordUserCtrlr: passwordUserCtrlr,
        );
      }
    // widget function that I need to pass on widget_fields.dart
      Widget togglePassword() {
        return IconButton(
          onPressed: () {
            setState(() {
              isSecuredPasswordField = !isSecuredPasswordField;
            });
          },
          icon: isSecuredPasswordField
              ? const Icon(Icons.visibility)
              : const Icon(Icons.visibility_off),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search