Creating Dynamic Forms & Get Data from Dynamic Forms in Flutter

By | April 4, 2021

Dynamic Forms in Flutter

Questions

  • How can we create dynamic forms in Flutter?
  • How can we access data from dynamic Forms?

Watch Video Tutorial


So let’s create a simple dynamic layout

We are gonna create a dynamic layout with one TexField when we tap on a plus button in the AppBar.

So this is how our AppBar is going to look like

AppBar(
    title: Text('Dynamic Form'),
    actions: [
        IconButton(
        icon: Icon(Icons.add),
        onPressed: () async {
            setState(() {
            _count++;
            });
        },
        ),
        IconButton(
        icon: Icon(Icons.refresh),
        onPressed: () async {
            setState(() {
            _count = 0;
            _result = '';
            });
        },
        )
    ],
 )

For simplicity we will be incrementing a local counter and adding those many dynamic TextFields.

So declare a variable _count and initialize it to zero.

The other button in the AppBar will reset it to zero.


Let’s create a dynamic List based on the counter with each form having a TextField.

_row(int index) {
    return Row(
      children: [
        Text('ID: $index'),
        SizedBox(width: 30),
        Expanded(
          child: TextFormField(),
        ),
      ],
   );
}

Now Let’s add it to a ListView.

Flexible(
    child: ListView.builder(
    shrinkWrap: true,
    itemCount: _count,
    itemBuilder: (context, index) {
        return _row(index);
    },
  ),
)

When the user taps the Counter button, it will add those many rows to the ListView.

Well, That’s all good!!.

But how do I get the values from the dynamic TextFields?
I can create a controller for each one and store it in a List of TextEditingControllers.

BUT!!!,

what if I have more than one textfields and other input fields????

No Way is that I going to create more controllers, that would be a bad idea.

So Let’s see how we can solve it.


The easies way is to create a List of Map, like this.

List<Map<String, dynamic>> _values;

Yeah, so let’s see how to make this work.

TextFormField(
    onChanged: (val) {
        _onUpdate(index, val);
    },
),

Here I assume the index is the key, you may have more complex objects in which you can use any of the member with unique value as a key.
The idea is to save the values in a json Object for each dynamic row.
Let’s see how we can achieve this.

You can see the ‘_onUpdate’ in the onChanged Event of the TextFormField. On this change, we are saving the value in a json object and adding to the _values array.


Let’s see how the method looks like.

_onUpdate(int index, String val) async {
    int foundKey = -1;
    for (var map in _values) {
      if (map.containsKey("id")) {
        if (map["id"] == index) {
          foundKey = index;
          break;
        }
      }
    }
    if (-1 != foundKey) {
      _values.removeWhere((map) {
        return map["id"] == foundKey;
      });
    }
    Map<String, dynamic> json = {
      "id": index,
      "value": val,
    };
    _values.add(json);
}

In the above method, we are saving the values in a json object and adding the json object to the _values array.
Before adding we are checking, if the key is already present, then remove that json object and add again. You can copy and modify the json object as well.


In this case I am using the ListView index as the key, but in a complex real world environment, you will have more solid meaningful keys.

In this way we save all the dynamic values from the dynamic form in a dynamic json list. It’s easy as it is.


Please leave your valuable comments below this post.
Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *