Flutter dropdownMenue with conditions

40 Views Asked by At

I'm creating two dropdown menues with the condition that the values in the second dropdown menu changes according to selected value in the first dropdown menu. I however keep getting this errro that LateInitializationError: Field 'selecItem' has not been initialized. This happens after I select the value in the first dropdown menu.

I don't understand it. can someone please explain it to me?

late List<String> department;
late String? selectedDepartment;
late List<String> adminTitle;
late List<String> technicalTitle;

@override
void initState(){
super.initState();
department = [
      widget.technicalDept,
      widget.adminDept
    ];
selectedDepartment = department[0];
if (selectedDepartment == department[0]) {
      selecItem = [
        widget.selectTitleString,
        widget.backEndDevString,
        widget.frontEndDevString,
        widget.networkEngString,
        widget.computerEngString,
      ];
      values = technicalTitle[0];
    }
if (selectedDepartment == department[1]) {
      selecItem = [
        widget.selectTitleString,
        widget.regionalAdminString,
        widget.sectorAdminString
      ];
      values = adminTitle[0];
    }
}

**in the build widget**
Row( children: [
         SizedBox(
            width: screenWidth * 0.1,//I defined media query for this
            child: Text("${widget.departmentString}:")),
         DropdownButton<String>(
            value: selectedDepartment,
            items: department.map((e) {
               return DropdownMenuItem(value: e, child: Text(e));
                          }).toList(),
                          onChanged: (value) {
                            setState(() {
                              selectedDepartment = value;
                            });
                          },
                        ),
                        selectedDepartment != department[0]
                            ? Row(
                                children: [
                                  SizedBox(
                                      width: screenWidth * 0.1,
                                      child:
                                          Text("${widget.selectTitleString}:")),
                                  DropdownButton<String>(
                                    value: values,
                                    items: selecItem!.map((e) {
                                      return DropdownMenuItem(
                                          value: e, child: Text(e));
                                    }).toList(),
                                    onChanged: (value) {
                                      setState(() {
                                        values = value;
                                      });
                                    },
                                  ),
                                ],
                              )
                            : const SizedBox()
                      ],
                    ),
1

There are 1 best solutions below

7
Yakubu On

your code failed due to an uninitialized late variable (selecItem) Make selecItem nullable and initializing it in initState and within the onChanged callback of the first dropdown to ensure it's always set before use

  List<String>? selecItem;

Here is sample

class MyWidget extends StatefulWidget {
  final String technicalDept;
  final String adminDept;
  final String selectTitleString;
  final String backEndDevString;
  final String frontEndDevString;
  final String networkEngString;
  final String computerEngString;
  final String regionalAdminString;
  final String sectorAdminString;
  final String departmentString;

  const MyWidget({
    Key? key,
    required this.technicalDept,
    required this.adminDept,
    required this.selectTitleString,
    required this.backEndDevString,
    required this.frontEndDevString,
    required this.networkEngString,
    required this.computerEngString,
    required this.regionalAdminString,
    required this.sectorAdminString,
    required this.departmentString,
  }) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late List<String> department;
  String? selectedDepartment;
  List<String>? selecItem;
  String? values;

  @override
  void initState() {
    super.initState();
    department = [widget.technicalDept, widget.adminDept];
    selectedDepartment = department[0];
    updateTitlesBasedOnDepartment();
  }

  void updateTitlesBasedOnDepartment() {
    if (selectedDepartment == department[0]) {
      selecItem = [
        widget.selectTitleString,
        widget.backEndDevString,
        widget.frontEndDevString,
        widget.networkEngString,
        widget.computerEngString,
      ];
    } else if (selectedDepartment == department[1]) {
      selecItem = [
        widget.selectTitleString,
        widget.regionalAdminString,
        widget.sectorAdminString,
      ];
    }
    values = selecItem?.first; 
  }

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;

    return Column(
      children: [
        Row(
          children: [
            SizedBox(width: screenWidth * 0.1, child: Text("${widget.departmentString}:")),
            DropdownButton<String>(
              value: selectedDepartment,
              items: department.map((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
              onChanged: (value) {
                setState(() {
                  selectedDepartment = value;
                  updateTitlesBasedOnDepartment();
                });
              },
            ),
          ],
        ),
        if (selectedDepartment == department[0] || selectedDepartment == department[1]) 
          Row(
            children: [
              SizedBox(width: screenWidth * 0.1, child: Text("${widget.selectTitleString}:")),
              DropdownButton<String>(
                value: values,
                items: selecItem?.map((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                onChanged: (value) {
                  setState(() {
                    values = value;
                  });
                },
              ),
            ],
          )
      ],
    );
  }
}

You can make a sample call here

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dropdown Example'),
        ),
        body: Center(
          child: MyWidget(
            technicalDept: 'Technical Department',
            adminDept: 'Administrative Department',
            selectTitleString: 'Select Title',
            backEndDevString: 'Backend Developer',
            frontEndDevString: 'Frontend Developer',
            networkEngString: 'Network Engineer',
            computerEngString: 'Computer Engineer',
            regionalAdminString: 'Regional Administrator',
            sectorAdminString: 'Sector Administrator',
            departmentString: 'Department',
          ),
        ),
      ),
    );
  }
}