0

What I am trying to do in my app is to add a dropdown based on the list contents. I have something like this:

[
    {
        id: val,
        displayName: Enter value,
        type: string, 
        value: "any"
    },
    {
        id: si,
        displayName: Source,
        type: list,
        value: [
            MO
        ],
        data: [
            {id: 1, displayId: MO},
            {id: 2, displayId: AO},
            {id: 3, displayId: OffNet}
        ]
     }
 ]

Currently there are 2 entries. What I want to do is display a dropdown containing those options (Enter value and Source) as 2 entries of dropdown:

  • If Enter value is selected a text box next to it should be displayed, since it has a type of string.
  • If Source option in dropdown is selected another dropdown containing those entries (MO, AO, Offnet) should be present as a dropdown value, since it has a type of list.

In short, based on the selection of the 1st dropdown a widget to be displayed (either text box or another dropdown) should be chosen.

If anyone knows or previously had done the same please help me with this, Thanks.

cegas
  • 2,823
  • 3
  • 16
  • 16
Mark12
  • 209
  • 1
  • 4
  • 8
  • I think you should have a look at [this](https://api.flutter.dev/flutter/material/DropdownButton-class.html) example. – Thor Oct 07 '19 at 06:27
  • https://pub.dev/packages/dropdown_formfield use this widget and use conditional statements based on drop down value to achieve this. – Hussnain Haidar Oct 07 '19 at 06:59
  • > Take a look this answer [Custom dropdown widget with default value](https://stackoverflow.com/questions/57869593/set-default-value-for-dropdown-button-in-flutter/57869718#57869718) – ibrahimkarahan Oct 07 '19 at 07:33

1 Answers1

0

I'd make use of StatefulWidget to achieve what you need (if you're not using more advanced state management options). State would be helpful to track user's choices, as well as to decide whether to render a text field or another dropdown (or nothing at all).

I've added a complete working example below. Note that it does not follow best practices in a sense that you would probably want to split it up in separate small widgets for better composability (and readability). However, I've opted for quick-and-dirty approach to fit everything in one place.

Also note that you'd probably want to do some more processing once a user makes a choice. Here, I simply illustrate how to render different widgets based on a user's choice (or more generally, changes in StatefulWidget's state). Hence, this example is used to highlight one principle only.

import 'package:flutter/material.dart';

void main() {
  runApp(DropdownExample());
}

class DropdownExample extends StatefulWidget {
  @override
  _DropdownExampleState createState() => _DropdownExampleState();
}

class _DropdownExampleState extends State<DropdownExample> {
  String type;
  int optionId;

  final items = [
    {
      "displayName": "Enter value",
      "type": "string",
    },
    {
      "displayName": "Source",
      "type": "list",
      "data": [
        {"id": 1, "displayId": "MO"},
        {"id": 2, "displayId": "AO"},
        {"id": 3, "displayId": "OffNet"}
      ]
    }
  ];

  @override
  Widget build(BuildContext context) {
    Widget supporting = buildSupportingWidget();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Dropdown Example")),
        body: Center(
          child: Container(
            height: 600,
            width: 300,
            child: Row(
              children: <Widget>[
                buildMainDropdown(),
                if (supporting != null) supporting,
              ],
            ),
          ),
        ),
      ),
    );
  }

  Expanded buildMainDropdown() {
    return Expanded(
      child: DropdownButtonHideUnderline(
        child: DropdownButton(
          value: type,
          hint: Text("Select a type"),
          items: items
              .map((json) => DropdownMenuItem(
                  child: Text(json["displayName"]), value: json["type"]))
              .toList(),
          onChanged: (newType) {
            setState(() {
              type = newType;
            });
          },
        ),
      ),
    );
  }

  Widget buildSupportingWidget() {
    if (type == "list") {
      List<Map<String, Object>> options = items[1]["data"];
      return Expanded(
        child: DropdownButtonHideUnderline(
          child: DropdownButton(
            value: optionId,
            hint: Text("Select an entry"),
            items: options
                .map((option) => DropdownMenuItem(
                    child: Text(option["displayId"]), value: option["id"]))
                .toList(),
            onChanged: (newId) => setState(() {
              this.optionId = newId;
            }),
          ),
        ),
      );
    } else if (type == "string") {
      return Expanded(child: TextFormField());
    }
    return null;
  }
cegas
  • 2,823
  • 3
  • 16
  • 16
  • Thank you for helping, got the idea how to implement something like this. but what if it has to get displayed inside the bottomsheet, then whenever the state changes as the result of change in dropdown menu as its not getting updated inside the bottom sheet – Mark12 Oct 07 '19 at 10:30
  • Looks like state needs to be propagated to bottom sheet so that it can react to it. However, I'm a bit hesitant to say with any conviction that this is the solution without seeing the code. I'd suggest creating another question (with a sample code) for this specific problem. – cegas Oct 07 '19 at 10:51
  • if the item List has changed I am getting exceptions, and the item list is not fixed it may contain as many text as well as Lists , so in first dropdown after selection its throwing exceptions – Mark12 Oct 08 '19 at 10:03
  • if I add one more to the List like this { "displayName": "Enter valuea", "type": "string", }, or A list like this { "id": "si", "displayName": "Source", "type": "list", "value": ["MO"], "searchField": "si", "data": [ {"id": 1, "displayId": "MO"}, {"id": 2, "displayId": "AO"}, {"id": 3, "displayId": "OffNet"} ] } I am getting exception – Mark12 Oct 08 '19 at 10:11
  • This is expected. The code example in the answer considers only the data that is in original question. You would have to adapt it to make sure that it does not depend on number of items or their order (example does), or repeated types. I'd suggest to read the following topic to understand the limitations of `DropdownButton`: [How to implement drop down list in flutter?](https://stackoverflow.com/questions/49273157/how-to-implement-drop-down-list-in-flutter/). See if it applies to your situation and if not - consider posting a new question with an error you're receiving and data you're passing. – cegas Oct 08 '19 at 10:46
  • Okay I will go through that, Thanks ! – Mark12 Oct 08 '19 at 14:02