Skip to content

Instantly share code, notes, and snippets.

@mingsai
Created September 2, 2021 09:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mingsai/7e3de879b7f41d5b7a6a6111d159e110 to your computer and use it in GitHub Desktop.
Save mingsai/7e3de879b7f41d5b7a6a6111d159e110 to your computer and use it in GitHub Desktop.
How to pass arguments between widgets in Flutter

How to pass arguments to a widget using a variable:

tldr; We have to turn our thinking on its head a bit. Data can be passed to the called widget when you navigate to it by using final arguments with default values in the destination widget. Using an optional function you can get data back from the 'child' (destination) widget.

In the destination stateful widget you create a final variable;

 final int boxIndex;

In the destination constructor give your final variable a constant default value

DestinationClassConstructor({Key? key, this.boxIndex = -1}): super(key: key);

You can add methods to the stateful widget class that use the value in some significant way:

e.g.

  bool isEditing() {
    return this.boxIndex != -1;
  }

In the source widget that calls the destination widget, you can pass in a value other than the default.

DestinationClassConstructor(boxIndex: 123),

In the destination widgets state content class you could use the value directly or call the method above:

e.g.

widget.isEditing()
widget.boxIndex,

The real power of this method happens when you decide that you can pass Functions as parameters:

e.g.

In your destination stateful widget create the nullable function call with its constructor argument:

final Function()? destinationWidgetTapped;

DestinationClassConstructor({Key? key, this.destinationWidgetTapped}): super(key: key);

Note: In this case the function variable is assigned a default value of null.

Somewhere in your destination content state widget call the function:

if (widget.destinationTapped != null) widget.destinationWidgetTapped!();

Then in your source widget make the call as follows:

DestinationClassConstructor(destinationWidgetTapped: () {
                        print('this code from the source widget executes after the child widget event is invoked');

                        Navigator.of(context).pop(); //pop the child widget
                      },

Which is fine and very useful when you consider that you can also pass back a value along with the function call.

final Function(String)? destinationWidgetTapped;

DestinationClassConstructor({Key? key, this.destinationWidgetTapped}): super(key: key);

Somewhere in your destination content state widget call the function:

if (widget.destinationTapped != null) widget.destinationWidgetTapped!('Hello from the Destination Content State Widget');

Then you can receive data like this:

DestinationClassConstructor(destinationWidgetTapped: (value) { 
    print('Data is passed from the destination widget with a string value of : $value');
    Navigator.of(context).pop();
},

Nota Bene:

Function(String) can also be written as ValueChanged<String>

We can further extrapolate that any object may be passed:

Function(Object?) written as ValueChanged<Object?>

And the argument might be better written as:

final ValueChanged<Object?>? onValueChanged;
DestinationClassConstructor({Key? key, this.onValueChanged}): super(key: key);

Which would allow one to send any data object, array, json, map, string, int, bool, etc. while maintaining access to a completion handler so that one could access the variable data in both directions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment