skip to Main Content

i have a firestore collection (conttyp) with documents (client, contractor, supplier, employee) and every document have only one (title) field like (عميل, مقاول, تاجر, موظف)

i’m trying to store the value as doc id to a list and save to another table (contact), but need to show the selected item (title) on the button instead of the document id (the value)

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

class TestScreen extends StatefulWidget {
  const TestScreen({super.key});

  @override
  State<TestScreen> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> {
  final _fireStore = FirebaseFirestore.instance;
  final _auth = FirebaseAuth.instance;
  late User loggedInUser;

  List<String> selectedTypeID = [];
  List<String> selectedTypeTitle = [];
  final TextEditingController textEditingController = TextEditingController();

  @override
  void dispose() {
    textEditingController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder(
            stream: _fireStore.collection('conttyp').snapshots(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return const Center(
                  child: LinearProgressIndicator(
                    backgroundColor: Colors.amber,
                  ),
                );
              } else {
                return DropdownButtonFormField2<String>(
                  isExpanded: true,
                  hint: const Text(
                    'اختر من القائمة',
                    style: TextStyle(fontFamily: 'Zahey'),
                  ),
                  items: snapshot.data!.docs.map((DocumentSnapshot item) {
                    return DropdownMenuItem<String>(
                      value: item.id,
                      //disable default onTap to avoid closing menu when selecting an item
                      enabled: false,
                      child: StatefulBuilder(
                        builder: (context, menuSetState) {
                          final isSelected = selectedTypeID.contains(item
                              .id) /*  && selectedTypeTitle.contains(item.get('title')) */;
                          return InkWell(
                            onTap: () {
                              isSelected
                                  ? {
                                      selectedTypeID.remove(item.id),
                                      selectedTypeTitle
                                          .remove(item.get('title'))
                                    }
                                  : {
                                      selectedTypeID.add(item
                                          .id),  
                                      selectedTypeTitle.add(item.get('title')) 
                                    };
                              //This rebuilds the StatefulWidget to update the button's text
                              setState(() {});
                              //This rebuilds the dropdownMenu Widget to update the check mark
                              menuSetState(() {});
                            },
                            child: Container(
                              height: double.infinity,
                              padding:
                                  const EdgeInsets.symmetric(horizontal: 16.0),
                              child: Row(
                                children: [
                                  isSelected
                                      ? const Icon(Icons.check_box_outlined)
                                      : const Icon(
                                          Icons.check_box_outline_blank),
                                  const SizedBox(width: 16),
                                  Text(
                                    item.get('title'),
                                    style: const TextStyle(
                                      fontSize: 14,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          );
                        },
                      ),
                    );
                  }).toList(),
                  value: selectedTypeTitle.isEmpty ? null : selectedTypeTitle.last,
                  onChanged: (value) {},
                  selectedItemBuilder: (context) {
                    return snapshot.data!.docs.map(
                      (item) {
                        return Container(
                          padding: const EdgeInsets.symmetric(horizontal: 16.0),
                          child: Text(
                            selectedTypeID.join(', '),
                            style: const TextStyle(
                              fontSize: 14,
                              overflow: TextOverflow.ellipsis,
                            ),
                            maxLines: 1,
                          ),
                        );
                      },
                    ).toList();
                  },
                  buttonStyleData: const ButtonStyleData(
                    height: 40,
                    width: 200,
                  ),
                  dropdownStyleData: const DropdownStyleData(
                    maxHeight: 200,
                  ),
                  menuItemStyleData: const MenuItemStyleData(
                    height: 40,
                  ),
                  dropdownSearchData: DropdownSearchData(
                    searchController: textEditingController,
                    searchInnerWidgetHeight: 50,
                    searchInnerWidget: Container(
                      height: 50,
                      padding: const EdgeInsets.only(
                        top: 8,
                        bottom: 4,
                        right: 8,
                        left: 8,
                      ),
                      child: TextFormField(
                        expands: true,
                        maxLines: null,
                        controller: textEditingController,
                        decoration: InputDecoration(
                          isDense: true,
                          contentPadding: const EdgeInsets.symmetric(
                            horizontal: 10,
                            vertical: 8,
                          ),
                          hintText: 'بحث...',
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(8),
                          ),
                        ),
                      ),
                    ),
                    searchMatchFn: (item, searchValue) {
                      return (item.value.toString().contains(searchValue));
                    },
                  ),
                  //This to clear the search value when you close the menu
                  onMenuStateChange: (isOpen) {
                    if (!isOpen) {
                      textEditingController.clear();
                    }
                  },
                );
              }
            }),
      ),
    );
  }
}

but getting an error of

items.where((DropdownMenuItem<T> item) { return item.value == value; }).length == 1': There should be exactly one item with [DropdownButton]'s value: عميل. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value)

the error screenshot

how to store the title field of the selected document id in another list?

2

Answers


  1. You are getting this error because you’re setting the value of DropdownButtonFormField2 to selectedTypeTitle.last, the last item added to the selectedTypeTitle list. so you can solve them like this,

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:dropdown_button2/dropdown_button2.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:flutter/material.dart';
    
    class TestScreen extends StatefulWidget {
      const TestScreen({super.key});
    
      @override
      State<TestScreen> createState() => _TestScreenState();
    }
    
    class _TestScreenState extends State<TestScreen> {
      final _fireStore = FirebaseFirestore.instance;
      final _auth = FirebaseAuth.instance;
      late User loggedInUser;
    
      List<String> selectedTypeID = [];
      List<String> selectedTypeTitle = [];
      final TextEditingController textEditingController = TextEditingController();
    
      @override
      void dispose() {
        textEditingController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: StreamBuilder(
                stream: _fireStore.collection('conttyp').snapshots(),
                builder: (context, snapshot) {
                  if (!snapshot.hasData) {
                    return const Center(
                      child: LinearProgressIndicator(
                        backgroundColor: Colors.amber,
                      ),
                    );
                  } else {
                    return Column(
                      children: [
                      DropdownButtonFormField2<String>(
                      isExpanded: true,
                      hint: const Text(
                        'اختر من القائمة',
                        style: TextStyle(fontFamily: 'Zahey'),
                      ),
                      items: snapshot.data!.docs.map((DocumentSnapshot item) {
                        return DropdownMenuItem<String>(
                          value: item.id,
                          //disable default onTap to avoid closing menu when selecting an item
                          enabled: false,
                          child: StatefulBuilder(
                            builder: (context, menuSetState) {
                              final isSelected = selectedTypeID.contains(item
                                  .id) /*  && selectedTypeTitle.contains(item.get('title')) */;
                              return InkWell(
                                onTap: () {
                                  isSelected
                                      ? {
                                    selectedTypeID.remove(item.id),
                                    selectedTypeTitle
                                        .remove(item.get('title'))
                                  }
                                      : {
                                    selectedTypeID.add(item
                                        .id),
                                    selectedTypeTitle.add(item.get('title'))
                                  };
                                  //This rebuilds the StatefulWidget to update the button's text
                                  setState(() {});
                                  //This rebuilds the dropdownMenu Widget to update the check mark
                                  menuSetState(() {});
                                },
                                child: Container(
                                  height: double.infinity,
                                  padding:
                                  const EdgeInsets.symmetric(horizontal: 16.0),
                                  child: Row(
                                    children: [
                                      isSelected
                                          ? const Icon(Icons.check_box_outlined)
                                          : const Icon(
                                          Icons.check_box_outline_blank),
                                      const SizedBox(width: 16),
                                      Text(
                                        item.get('title'),
                                        style: const TextStyle(
                                          fontSize: 14,
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              );
                            },
                          ),
                        );
                      }).toList(),
                      value: selectedTypeTitle.isEmpty ? null : selectedTypeTitle.last,
                      onChanged: (value) {},
                      selectedItemBuilder: (context) {
                        return snapshot.data!.docs.map(
                              (item) {
                            return Container(
                              padding: const EdgeInsets.symmetric(horizontal: 16.0),
                              child: Text(
                                selectedTypeID.join(', '),
                                style: const TextStyle(
                                  fontSize: 14,
                                  overflow: TextOverflow.ellipsis,
                                ),
                                maxLines: 1,
                              ),
                            );
                          },
                        ).toList();
                      },
                      buttonStyleData: const ButtonStyleData(
                        height: 40,
                        width: 200,
                      ),
                      dropdownStyleData: const DropdownStyleData(
                        maxHeight: 200,
                      ),
                      menuItemStyleData: const MenuItemStyleData(
                        height: 40,
                      ),
                      dropdownSearchData: DropdownSearchData(
                        searchController: textEditingController,
                        searchInnerWidgetHeight: 50,
                        searchInnerWidget: Container(
                          height: 50,
                          padding: const EdgeInsets.only(
                            top: 8,
                            bottom: 4,
                            right: 8,
                            left: 8,
                          ),
                          child: TextFormField(
                            expands: true,
                            maxLines: null,
                            controller: textEditingController,
                            decoration: InputDecoration(
                              isDense: true,
                              contentPadding: const EdgeInsets.symmetric(
                                horizontal: 10,
                                vertical: 8,
                              ),
                              hintText: 'بحث...',
                              border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(8),
                              ),
                            ),
                          ),
                        ),
                        searchMatchFn: (item, searchValue) {
                          return (item.value.toString().contains(searchValue));
                        },
                      ),
                      //This to clear the search value when you close the menu
                      onMenuStateChange: (isOpen) {
                        if (!isOpen) {
                          textEditingController.clear();
                        }
                      },
                    );
                  }
                }),
            ElevatedButton(
              onPressed: () {
                _fireStore.collection('orders').add({
                  'user': loggedInUser.email,
                  'selectedTypeTitle': selectedTypeTitle,
                });
              },
              child: const Text('Submit'),
            ),
            ],
          ),
        ),
        );
      }
    }
    
    Login or Signup to reply.
  2. You should use id for your value instead of title:

    value: selectedTypeID.isEmpty ? null : selectedTypeID.last
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search