Search code examples
flutterlistdrop-down-menudropdown

Showing the dropdown list with special List and Multiple Dynamic Dependent Dropdown List


List<Map<String, dynamic>> category123 = [
    {
      "name": "Python",
      "department": "second-choice",
      "detail": ['11', '12', '13', '14'],
     
    },
    {
      "name": "Javascript",
      "department": "first-choice",
      "detail": ['21', '22', '23', '24'],
      
    },
    {
      "name": "PHP",
       "department": "first-choice",
      "detail": ['31', '32', '33', '34'],
     
    },
    {
      "name": "C#",
          "department": "second-choice",
      "detail": ['41', '42', '43', '44'],
  
    },
    {
      "name": "Java",
           "department": "first-choice",
      "detail": ['51', '52', '53', '54'],
 
    },
    {
      "name": "C++",
          "department": "second-choice",
      "detail": ['61', '62', '63', '64'],
  
    },
     {
      "name": "Erlang",
          "department": "first-choice",
      "detail": ['71', '72', '73', '74'],
  
    },
  ];

Is it possibly make this List become like picture result? and I also want the detail (list) will be display in other list based on the which "name" is selected.

enter image description here

For the dependents, if i select the JavaScript in selection, in another dropdown list should show the detail List of the Javascript including 11, 12, 13, 14


Solution

  • Take a look at this:

    import 'package:collection/collection.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      MyApp({super.key});
    
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      List<Map<String, dynamic>> category123 = [
        {
          "name": "Python",
          "department": "second-choice",
          "detail": ['11', '12', '13', '14'],
        },
        {
          "name": "Javascript",
          "department": "first-choice",
          "detail": ['21', '22', '23', '24'],
        },
        {
          "name": "PHP",
          "department": "first-choice",
          "detail": ['31', '32', '33', '34'],
        },
        {
          "name": "C#",
          "department": "second-choice",
          "detail": ['41', '42', '43', '44'],
        },
        {
          "name": "Java",
          "department": "first-choice",
          "detail": ['51', '52', '53', '54'],
        },
        {
          "name": "C++",
          "department": "second-choice",
          "detail": ['61', '62', '63', '64'],
        },
        {
          "name": "Erlang",
          "department": "first-choice",
          "detail": ['71', '72', '73', '74'],
        },
      ];
    
      late final List data;
      dynamic selectedItem;
      String? selectedDetail;
    
      @override
      void initState() {
        final groups = groupBy(category123, (Map e) => e['department']);
    
        data = [
          for (final item in groups.entries)
            for (final value in [item.key, ...item.value])
              if (value is Map)
                {'value': value, 'bold': false}
              else
                {'value': value, 'bold': true}
        ];
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
                body: Center(
                    child: Column(
          children: [
            DropdownButton<dynamic>(
                value: selectedItem,
                items: [
                  for (final item in data)
                    item['bold'] == true
                        ? DropdownMenuItem(
                            enabled: false,
                            child: Text(item['value'],
                                style:
                                    const TextStyle(fontWeight: FontWeight.bold)))
                        : DropdownMenuItem(
                            value: item['value'],
                            child: Padding(
                              padding: const EdgeInsets.only(left: 8),
                              child: Text(item['value']['name']),
                            ))
                ],
                onChanged: (value) {
                  setState(() {
                    selectedItem = value;
                  });
                }),
            if (selectedItem != null)
              DropdownButton<String>(
                  value: selectedItem['detail'].contains(selectedDetail)
                      ? selectedDetail
                      : null,
                  items: [
                    for (final item in selectedItem['detail'])
                      DropdownMenuItem(value: item, child: Text(item))
                  ],
                  onChanged: (value) {
                    setState(() {
                      selectedDetail = value;
                    });
                  })
          ],
        ))));
      }
    }