Passing data from a child widget to a parent widget in Flutter

Jehad Nasser
Flutter Community
Published in
5 min readOct 8, 2019

There’s (at least) two ways to pass data from a child widget to a parent widget in Flutter; Shared object using Singleton pattern or callbacks. I am leaving the Singleton pattern using BLoC to another day, so this article talks only about callbacks.

If you are in a hurry, follow this gist.

A real life use case

Imagine that you have created a Voting App; where users can vote for the best mobile development framework. And this app consists of 5 widgets, Just as simple as this:

1- Text widget displays ‘Vote for the best Mobile App framework:’.
2-
Two Buttons widgets; Flutter & React.
3-
RichText widget displays ‘You voted for: ….’.
4- A widget to represents the Home Screen and contains all other widgets.

Most of this work is completely usual, except the data-binding part, in other words ‘passing data of the selected name (Flutter/React) from the clicked-button to the RichText’ so RichText can display it: ‘You voted for: Flutter’.

The “just working” approach

“It is not enough for code to work.”
― Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

Will not go in details with this approach as it’s not clean nor scalable at all. Anyway, this can be achieved by building all previous widgets inside the same parent(Home Screen widget), so they all can access same global variables, where this variables can be used as a data pool to share data between widgets. See this diagram:

All inside one widget

and the project structure would be something like this:

everything inside one file/widget

The Callback approach

Only one thing special about this approach; it’s a clean and well-written code. With this approach you can achieve some kind of “separation of concerns (SoC)” between widgets. And the project structure could be something like this; each widget live in its own small world:

You can see many widgets in the project structure(and it’s not the best structure ever, only an example):
my_card: is a custom widget to build a voting item like Flutter Button, React Button in our example.
my_voting_result: is a custom widget gets the selected my_card’s data, and display it as text: ‘You voted for: ….’.
my_board: is a custom widget to wrap all the voting widgets, so I can keep Home clean by wrap everything inside ‘my_board’ and just use it as a widget inside ‘home’.

Each widget live in its world.

As we said before, we are trying to bind two widgets, the child(the wrapped) which is here the Buttons(my_card), and the parent(wrapper) which is here the ‘my_board’, so whenever something changed in the child widget(the button clicked), a the parent will know about it, and update the text. How?
- using a Callback, which is a supernatural function with many abilities; it can access the parent variables, and also can be called from inside the child with data(arguments) from the child.
- I know that, but how this works?

Let me explain the steps using a very simple use case; a child widget pass an integer number ‘id’ to its parent widget, then the parent takes that integer and update its id value:

simple example

Steps to create a callback:

Step 1: Please be aware that we have two sides here; parent and child, they need a blueprint(template/signature) of the thing they will exchange before they exchange it. And as they need to exchange a function(callback) we need to define this function’s template(blueprint/signature), to do so we use ‘typedef’ keyword followed by a function’s signature like this:

this needs to be done inside the child widget as it is going to use it.

Step 2: Configure the child to expect a callback(a function) with the defined signature ‘IntCallback’ in the constructor:

Step 3: Connect the expected function with any action could happen inside the child e.g onPressed/onTap/onLoad..etc, So once this action triggered, the passed function(callback) will be called with the data you want to pass to the parent.

Note: Data will be passed as parameter(see elementId).

Step 4: Inside the Parent widget; Create a function with the same signature as the callback template in the child, so it will be accepted in the constructor. Also define variables in the parent so it can be accessible by the create function and the consumer for the return data from the child.

Step 5: Pass the callback in the child’s constructor:

See this diagram which explain the connection between the widgets and the callback template:

Child-Parent-Template relation, data not passed yet.

In this diagram, Inside the child widget, we created a function’s template(blueprint/function’s signature), As I said, this can be used to tell the child; “expect a function follows this template to be passed to you as a parameter and execute it when the time come.”.

In the other side, the parent widget side, we created a function, which also follows the same template as it will be passed to the child widget, and this template-clone-function does only one thing, receive data from the child widget and updates the variables in the parent with these values.

Then once the button clicked, data will be passed from the child to the parent using the callback function(function follows the template and can be passed as a parameter):

Passed function(Callback) executed and data passed.

See my other example(voting board) code on Github here.

https://www.twitter.com/FlutterComm

--

--