FadyFouad
FadyFouad

Reputation: 948

Cannot change Dropdown button value Flutter

I want to get the initial value of the Dropdown button from firebase; but when I try to set the governorateDDValue = selectedUser.governorate; inside the build method the value of Dropdown get the value from firebase but I cannot change it

DropdownButton.gif

this my code

class UserInfo extends StatefulWidget {
  static const routeName = '/UserInfoScreen';

  const UserInfo({Key? key}) : super(key: key);

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

class _UserInfoState extends State<UserInfo> {

  late User selectedUser;
  final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();

  var governorateDDValue;

  @override
  Widget build(BuildContext context) {

    final userList= Provider.of<List<User>>(context);
    final userID = ModalRoute.of(context)!.settings.arguments as String;
    selectedUser =
        userList.firstWhere((user) => user.id == userID);

    // this line makes dropdown value always equal to value from firestore
    governorateDDValue = selectedUser.governorate;

    return Scaffold(
      appBar: AppBar(
        title: Text('report'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Row(
            children: <Widget>[
                    Text('Governorate',),
                    Container(height: 5),
                    DropdownButton<String>(
                      value: governorateDDValue,
                      icon: const Icon(Icons.arrow_downward),
                      iconSize: 24,
                      elevation: 16,
                      style: const TextStyle(color: Colors.deepPurple),
                      onChanged: (String? newValue) {
                        setState(() {
                          governorateDDValue = newValue!;
                        });
                      },
                      items: Constants.governoratesOfEgypt
                          .map<DropdownMenuItem<String>>((String value) {
                        return DropdownMenuItem<String>(
                          value: value,
                          child: Text(value),
                        );
                      }).toList(),
          ),
        ],
      ),
    ),
  ),
);

} }

thanks in advance

Upvotes: 2

Views: 87

Answers (2)

Ahmed Megoo
Ahmed Megoo

Reputation: 26

Because you use governorateDDValue = selectedUser.governorate; inside build widget so the Dropdown menu will reset its value every time you change it the build widget will rebuild and the value of the dropdown will stay equal to the value from firebase you should use governorateDDValue = selectedUser.governorate; outside the build widget this code should work will

class UserInfo extends StatefulWidget {
  static const routeName = '/UserInfoScreen';

  const UserInfo({Key? key}) : super(key: key);

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

class _UserInfoState extends State<UserInfo> {

  var loading = false;

  late User selectedUser;
  final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();

  var governorateDDValue;


  @override
  void initState() {
    super.initState();
    loading = true;
    print('Future.delayed outside');
    print(loading);
    Future.delayed(Duration.zero, () {
      governorateDDValue = selectedUser.governorate;
      setState(() {
        loading = false;
      });
    });
  }


  @override
  Widget build(BuildContext context) {
    final userList = Provider.of<List<User>>(context);
    final userID = ModalRoute
        .of(context)!
        .settings
        .arguments as String;
    selectedUser =
        userList.firstWhere((user) => user.id == userID);

    // this line makes dropdown value always equal to value from firestore
    governorateDDValue = selectedUser.governorate;

    return Scaffold(
      appBar: AppBar(
        title: Text('report'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Row(
            children: <Widget>[
              Text('Governorate',),
              Container(height: 5),
              DropdownButton<String>(
                value: governorateDDValue,
                icon: const Icon(Icons.arrow_downward),
                iconSize: 24,
                elevation: 16,
                style: const TextStyle(color: Colors.deepPurple),
                onChanged: (String? newValue) {
                  setState(() {
                    governorateDDValue = newValue!;
                  });
                },
                items: Constants.governoratesOfEgypt
                    .map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
              ),
            ],
          ),
        ),
      ),
    );

Upvotes: 1

Mayb3Not
Mayb3Not

Reputation: 480

The reason why you cannot change it is because every time setState is called your build method is called. Therefore your value will always be set to governorateDDValue = selectedUser.governorate; So to allow changes you should place this governorateDDValue = selectedUser.governorate; in iniState

Or what you can do is like this so that it will only set it once

class UserInfo extends StatefulWidget {
  static const routeName = '/UserInfoScreen';

  const UserInfo({Key? key}) : super(key: key);

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

class _UserInfoState extends State<UserInfo> {

  late User selectedUser;
  final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
  bool initState = true; // ADD HERE
  var governorateDDValue;

  @override
  Widget build(BuildContext context) {

    final userList= Provider.of<List<User>>(context);
    final userID = ModalRoute.of(context)!.settings.arguments as String;
    selectedUser =
        userList.firstWhere((user) => user.id == userID);

    // this line makes dropdown value always equal to value from firestore
    if(initState){  // ADD HERE
    governorateDDValue = selectedUser.governorate; 
    initState = false;  // ADD HERE
    }

    return Scaffold(
      appBar: AppBar(
        title: Text('report'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Row(
            children: <Widget>[
                    Text('Governorate',),
                    Container(height: 5),
                    DropdownButton<String>(
                      value: governorateDDValue,
                      icon: const Icon(Icons.arrow_downward),
                      iconSize: 24,
                      elevation: 16,
                      style: const TextStyle(color: Colors.deepPurple),
                      onChanged: (String? newValue) {
                        setState(() {
                          governorateDDValue = newValue!;
                        });
                      },
                      items: Constants.governoratesOfEgypt
                          .map<DropdownMenuItem<String>>((String value) {
                        return DropdownMenuItem<String>(
                          value: value,
                          child: Text(value),
                        );
                      }).toList(),
          ),
        ],
      ),
    ),
  ),
);
}

Upvotes: 1

Related Questions