Max
Max

Reputation: 1301

The element that is selected in the DropdownButton is not displayed in button

Guys please tell me how to solve the problem. I'm using DropdownButton with Checkboxlisttile and ran into a problem that when selecting items, the selected item is not shown in the DropdownButto in the button itself, not in the list (I attached a screenshot below), am I doing something wrong and understand what needs to be fixed to show the selected item? I use packs for style: [getwidget][1] and [dropdown_button2][2]

code

 class DropdownWidget extends StatefulWidget {
  List<String> items;
  SvgPicture? icon;
  double width;

  DropdownWidget({
    Key? key,
    required this.items,
    required this.icon,
    required this.width,
  }) : super(key: key);

  @override
  State<DropdownWidget> createState() => _DropdownWidgetState();
}

class _DropdownWidgetState extends State<DropdownWidget> {
  String? selectedValue;
  bool selected = false;

  final List _selectedTitles = [];
  final List _selectedTitlesIndex = [];

  final GFCheckboxType type = GFCheckboxType.basic;

  @override
  void initState() {
    super.initState();
    if (widget.items.isNotEmpty) {
      _selectedTitles.add(widget.items[3]);
    }
  }

  void _onItemSelect(bool selected, int index) {
    if (selected == true) {
      setState(() {
        _selectedTitles.add(widget.items[index]);
        _selectedTitlesIndex.add(index);
      });
    } else {
      setState(() {
        _selectedTitles.remove(widget.items[index]);
        _selectedTitlesIndex.remove(index);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: widget.width,
      child: DropdownButtonHideUnderline(
        child: DropdownButton2(
          items: List.generate(
            widget.items.length,
            (index) => DropdownMenuItem<String>(
              value: widget.items[index],
              child: Container(
                decoration: BoxDecoration(
                  border: Border(
                    bottom: BorderSide(
                      color: constants.Colors.white.withOpacity(0.1),
                      width: 1,
                    ),
                  ),
                ),
                child: StatefulBuilder(
                  builder: (context, setStateSB) => GFCheckboxListTile(
                    value: _selectedTitles.contains(widget.items[index]),
                    onChanged: (bool selected) {
                      _onItemSelect(selected, index);
                      setStateSB(() {});
                    },
                    selected: selected,
                    title: Text(
                      widget.items[index],
                      style: constants.Styles.smallTextStyleWhite,
                    ),
                    padding: const EdgeInsets.only(top: 14, bottom: 13),
                    margin: const EdgeInsets.only(right: 12, left: 2),
                    size: 22,
                    activeBgColor: constants.Colors.greyCheckbox,
                    activeBorderColor: constants.Colors.greyCheckbox,
                    inactiveBgColor: constants.Colors.greyCheckbox,
                    activeIcon: SvgPicture.asset(constants.Assets.checkboxIcon),
                    inactiveBorderColor: constants.Colors.greyXMiddle,
                    type: type,
                  ),
                ),
              ),
            ),
          ),
          value: selectedValue,
          onChanged: (value) {
            setState(() {
              selectedValue = value as String;
            });
          },
          icon: SvgPicture.asset(constants.Assets.arrowDropdown),
          iconSize: 21,
          buttonHeight: 27,
          itemHeight: 66,
          dropdownMaxHeight: 191,
          dropdownWidth: 140,
          dropdownDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(8),
            border: Border.all(
              color: constants.Colors.purpleMain,
            ),
            color: constants.Colors.greyDark,
          ),
          selectedItemBuilder: (context) {
            return _selectedTitles.map(
              (item) {
                return Row(
                  children: [
                    widget.icon ?? const SizedBox(),
                    const SizedBox(width: 8),
                    Text(
                      item,
                      style: constants.Styles.bigBookTextStyleWhite,
                    ),
                  ],
                );
              },
            ).toList();
          },
        ),
      ),
    );
  }
}

list

 final List<String> carList = const [
    "All EV's",
    'Main EV',
    '<EV2>',
  ];

Upvotes: 0

Views: 90

Answers (2)

AJ-
AJ-

Reputation: 1783

as you are using a Dropdown widget as a workaround, I prepared a real solution for you that achieves exactly what you are looking for:

return Container(
  width: 150,
  child: PopupMenuButton(
    offset: Offset(0, 50),
    child: Padding(
      padding: EdgeInsets.symmetric(
        horizontal: 10, 
        vertical: 20
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          if (_selectedTitles.isNotEmpty)
          Text("<"),
          Flexible(
            child: Text(
              _selectedTitles.isEmpty
              ? "Select a value"
              : _selectedTitles.map((item) => item).toList().join(", "),
              overflow: TextOverflow.ellipsis,
            ),
          ),

          if (_selectedTitles.isNotEmpty)
          Text(">"),

          SizedBox(width: 5),
          Icon(Icons.arrow_drop_down)
        ],
      ),
    ),
    itemBuilder: (context) => List.generate(
      widget.items.length,
      (index) => PopupMenuItem(
        value: widget.items[index],
        child: Container(
          decoration: BoxDecoration(
            border: Border(
              bottom: BorderSide(
                // color: constants.Colors.white.withOpacity(0.1),
                width: 1,
              ),
            ),
          ),
          child: StatefulBuilder(
            builder: (context, setStateSB) => CheckboxListTile(
              value: _selectedTitles.contains(widget.items[index]),
              onChanged: (bool? selected) {
                _onItemSelect(selected!, index);
                setStateSB(() {});
              },
              selected: selected,
              title: Text(
                widget.items[index],
              ),
            ),
          ),
        ),
      ),
    )
  ),
);

here I add another example on how to have inside your popup, 2 buttons that allow you to select all values or unselect them:

      String? selectedValue;
    
      final List<String> _selectedTitles = [];
      final List<int> _selectedTitlesIndex = [];
    
      // final GFCheckboxType type = GFCheckboxType.basic;
    
      @override
      void initState() {
        super.initState();
        // if (widget.items.isNotEmpty) {
        //   _selectedTitles.add(widget.items[0]);
        // }
      }
    
      void _onItemSelect(bool selected, int index) {
        setState(() {
        if (selected == true) {
          _selectedTitles.add(widget.items[index]);
          _selectedTitlesIndex.add(index);
        } else {
          _selectedTitles.remove(widget.items[index]);
          _selectedTitlesIndex.remove(index);
        }
        });
      }
    
      void _selectAll(bool selected) {
        setState(() {
          if (selected == true) {
            _selectedTitles.clear();
            _selectedTitles.addAll(widget.items);
            _selectedTitlesIndex.clear();
            for( int i = 0 ; i <= widget.items.length; i++ ) { 
              _selectedTitlesIndex.add(i); 
            }
          } else {
            _selectedTitles.clear();
            _selectedTitlesIndex.clear();
          }
          Navigator.of(context).pop();
        });
      }
    
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 150,
      child: PopupMenuButton(
        offset: Offset(0, 50),
        child: Padding(
          padding: EdgeInsets.symmetric(
            horizontal: 0, 
            vertical: 20
          ),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              if (_selectedTitles.isNotEmpty)
              Text("<"),
              Flexible(
                child: Text(
                  _selectedTitles.isEmpty
                  ? "Select a value"
                  : _selectedTitles.map((item) => item).toList().join(", "),
                  overflow: TextOverflow.ellipsis,
                ),
              ),

              if (_selectedTitles.isNotEmpty)
              Text(">"),

              SizedBox(width: 5),
              Icon(Icons.arrow_drop_down)
            ],
          ),
        ),


        itemBuilder: (context) {
          List<PopupMenuEntry> items1 = List.generate(
            widget.items.length,
            (index) => PopupMenuItem(
              padding: EdgeInsets.zero,
              value: widget.items[index],
              child: Container(
                decoration: BoxDecoration(
                  border: Border(
                    bottom: index == widget.items.length - 1
                    ? BorderSide.none
                    : BorderSide(
                      // color: constants.Colors.white.withOpacity(0.1),
                      width: 1,
                    ),
                  ),
                ),
                child: StatefulBuilder(
                  builder: (context, setStateSB) => CheckboxListTile(
                    value: _selectedTitles.contains(widget.items[index]),
                    onChanged: (bool? selected) {
                      _onItemSelect(selected!, index);
                      setStateSB(() {});
                    },
                    selected: false,
                    title: Text(
                      widget.items[index],
                    ),
                  ),
                ),
              ),
            ),
          );
          return [
            PopupMenuItem(
              value: "select all",
              padding: EdgeInsets.zero,
              child: Container(
                decoration: BoxDecoration(
                  border: Border(
                    bottom: BorderSide(
                      // color: constants.Colors.white.withOpacity(0.1),
                      width: 1,
                    ),
                  ),
                ),
                child: Row(
                  children: [
                    TextButton(
                      child: Text(
                        "Select all",
                      ),
                      onPressed: () {
                        _selectAll(true);
                      },
                    ),
                    Spacer(),
                    TextButton(
                      child: Text(
                        "Unselect all",
                      ),
                      onPressed: () {
                        _selectAll(false);
                      },
                    )
                  ],
                ),
              ),
            ),
            ...items1
          ];
        }
      ),
    );
  }

Upvotes: 1

Abdulkarim
Abdulkarim

Reputation: 587

try this

import 'package:flutter/material.dart';


class DropdownWidget extends StatefulWidget {

List<String> items;

DropdownWidget({
Key? key,
required this.items,
}) : super(key: key);

@override
State<DropdownWidget> createState() => _DropdownWidgetState();
 }

class _DropdownWidgetState extends State<DropdownWidget> {
 String? selectedValue;
 bool selected = false;

 int selectedInd = 0 ;

final List _selectedTitles = [];
final List _selectedTitlesIndex = [];

@override
void initState() {
super.initState();
if (widget.items.isNotEmpty) {
  _selectedTitles.add(widget.items[0]);
}else{
  print("null");
  }
 }

 void _onItemSelect(bool selected, int index) {
 if (selected == true) {
  setState(() {
    _selectedTitles.add(widget.items[index]);
    _selectedTitlesIndex.add(index);
  });
  } else {
  setState(() {
    selectedInd = index ;
    _selectedTitles.remove(widget.items[index]);
    _selectedTitlesIndex.remove(index);
  });
   }
   }

  @override
  Widget build(BuildContext context) {
  return SizedBox(
      width: 150,
    child: DropdownButtonHideUnderline(
      child: DropdownButton(
        hint : Center(child: Text(_selectedTitles.isEmpty ? "selectedEV" 
        : _selectedTitles[selectedInd] , textAlign: TextAlign.end,)) ,
        items: List.generate(
          widget.items.length,
          (index) => DropdownMenuItem<String>(
            value: widget.items[index],
            child: Container(
              decoration: BoxDecoration(
                border: Border(
                  bottom: BorderSide(
                    color: Colors.white.withOpacity(0.1),
                    width: 1,
                  ),
                ),
              ),
              child: StatefulBuilder(
                builder: (context, setStateSB) => CheckboxListTile(
                  value: _selectedTitles.contains(widget.items[index]),
                  onChanged: (bool? selected) {
                    _onItemSelect(selected!, index);
                    setStateSB(() {});
                  },
                  selected: selected,
                  title: Text(
                    widget.items[index],
                  ),
                ),
              ),
            ),
          ),
        ),
        value: selectedValue,
        onChanged: (value) {
          setState(() {
            selectedValue = value as String;
            print(value);
          });
        },
        icon: Icon(Icons.arrow_drop_down),
        iconSize: 21,
        itemHeight: 66,
        selectedItemBuilder: (context) {
          return _selectedTitles.map(
            (item) {
              return Row(
                children: [
                  const SizedBox(width: 8),
                  Text(
                    item,
                  ),
                ],
              );
            },
          ).toList();
        },
      ),
    ),

   );
   }
   }

Upvotes: 0

Related Questions