简体   繁体   中英

How do I pass the value selected from DropDown menu to a stateful widget right below it in Flutter/Dart?

I need the user to select a value from a DropDown menu. Based on the value selected, a second DropDown is populated with values from the DB. I tried the following approach and it works when the user selects a value for the first time.

First DropDown:

            DropdownButton<String>(
                hint: Text('Please select your State/UT'),
                style: TextStyle(color: kPrimaryGrey),
                focusColor: kPrimaryBlue,
                value: selectedState,
                items: states.map((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                onChanged: (val) {
                  setState(() {
                    selectedState = val;
                  });
                }),
            SizedBox(
              height: 25.0,
            ),
            selectedState == null
                ? SizedBox(
                    height: 0.0,
                  )
                : CampusSelector(
                    inputState: selectedState,
                  ),

Second DropDown Using a FutureBuilder (SearchableDropdown):

class CampusSelector extends StatefulWidget {
  final String inputState;
  CampusSelector({this.inputState});
  @override
  _CampusSelectorState createState() => _CampusSelectorState();
}

class _CampusSelectorState extends State<CampusSelector> {
  var allInstitutions = {};
  QuerySnapshot stateData;
  List<DropdownMenuItem> listOfDistricts = [];
  List<DropdownMenuItem> listOfInstitutions = [];
  List<DropdownMenuItem> listOfInsAndDisTmp = [];
  List<DropdownMenuItem> listOfInsAndDis = [];
  Future<void> getStateData;
  List<String> institutions = [];

  Future<void> fetchInstitutions(inputState) async {
    List<String> institutionsTmp = [];
    listOfInstitutions = [];
    List<InstitutionAndDistrict> institutionsAndLocation = [];

    stateData = await _db
        .collection('institutions')
        .where('STATE', isEqualTo: inputState)
        .getDocuments();
    for (int i = 0; i < stateData.documents.length; i++) {
      String ins = stateData.documents[i].data['NAME_OF_INSTITUTION'];
      String dis = stateData.documents[i].data['DISTRICT'];
      institutionsTmp.add(stateData.documents[i].data['NAME_OF_INSTITUTION']);
      institutionsAndLocation
          .add(InstitutionAndDistrict(institution: ins, district: dis));
    }

    // Deduplication and Sorting

    institutions = institutionsTmp.toSet().toList();
    institutions.sort((a, b) => a.toString().compareTo(b.toString()));

    debugPrint(institutions.toString());

    for (int i = 0; i < institutions.length; i++) {
      listOfInstitutions.add(DropdownMenuItem(
        child: Text(institutions[i]),
        value: institutions[i],
      ));
    }

    for (int i = 0; i < institutionsAndLocation.length; i++) {
      listOfInsAndDisTmp.add(DropdownMenuItem(
        child: ListTile(
          title: Text(institutionsAndLocation[i].institution),
          subtitle: Text(institutionsAndLocation[i].district),
        ),
        value: institutionsAndLocation[i].institution,
      ));
    }

    setState(() {
      listOfInsAndDis = listOfInsAndDisTmp;
    });
  }

  @override
  void initState() {
    getStateData = fetchInstitutions(selectedState);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: getStateData,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return SearchableDropdown.single(
              items: listOfInsAndDis,
              value: selectedInstitution,
              hint: "Please select your college/university",
              searchHint: "Select one",
              onChanged: (value) {
                setState(() {
                  selectedInstitution = value;
                  for (int i = 0; i < stateData.documents.length; i++) {
                    if (stateData.documents[i].data['NAME_OF_INSTITUTION'] ==
                        value) {
                      selectedDistrict =
                          stateData.documents[i].data['DISTRICT'];
                    }
                  }
                  print(selectedInstitution);
                  print(selectedDistrict);
                });
              },
              isExpanded: true,
            );
          } else {
            return SizedBox(
              height: 0.0,
            );
          }
        });
  }
}

CampusSelector class is still a work-in-progress, hence the unruly bunch of lists to process the data.

You populate your CampusBuilder class once in initState . If you want to populate it with different data on each build , you need to call the fetchInstitutions methods in the build method.

That will probably mean you have to use a FutureBuilder .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM