skip to Main Content

here an example on how my code works having a TextFormField that actually change when updateValue as called
countryDropDownCustomKey.currentState?.updateValue(_initialCountryData);
meanwhile the CountryDropDown doesn’t…
Here I’ve recreated a StateFulWidget and I’ve using a GlobalKey to address the state

I’ve spent 12 hours trying to figure this out… please help
thank you

class CountryDropDownCustom extends StatefulWidget {
  CountryDropDownCustom({super.key, this.initialCountryData, required this.onChanged});
  PhoneCountryData? initialCountryData;
  final ValueChanged<PhoneCountryData> onChanged;

  @override
  State<CountryDropDownCustom> createState() => CountryDropDownCustomState();
}

class CountryDropDownCustomState extends State<CountryDropDownCustom> {
  PhoneCountryData? _initialCountryCode;
  late TextEditingController countryCode;

  void updateValue(PhoneCountryData? newValue) {
    setState(() {
      _initialCountryCode = newValue;
      countryCode = TextEditingController(text: _initialCountryCode?.countryCode?.toString() ?? '');
    });
  }

  @override
  void initState() {
    _initialCountryCode = widget.initialCountryData;
    countryCode = TextEditingController(text: _initialCountryCode?.countryCode?.toString() ?? '');
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
            flex: 1,
            child: TextFormField(
              controller: countryCode,
              decoration: textInputDecoration,
            )),
        const SizedBox(
          width: 5,
        ),
        Expanded(
          flex: 4,
          child: CountryDropdown(
            initialCountryData: _initialCountryCode,
            selectedItemBuilder: (phoneCountryData) {
              return Row(
                children: [
                  Padding(
                    padding: const EdgeInsets.only(right: 10.0),
                    child: CountryFlag(
                      height: 20,
                      width: 30,
                      countryId: phoneCountryData.countryCode!,
                    ),
                  ),
                  Flexible(
                    child: Text(
                      '+${phoneCountryData.phoneCode} - ${phoneCountryData.country}',
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                ],
              );
            },
            listItemBuilder: (phoneCountryData) {
              return Row(
                children: [
                  Padding(
                    padding: const EdgeInsets.only(right: 2.0),
                    child: CountryFlag(
                      height: 20,
                      width: 30,
                      countryId: phoneCountryData.countryCode!,
                    ),
                  ),
                  Flexible(
                    child: Text(
                      '+${phoneCountryData.phoneCode} - ${phoneCountryData.country}',
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                ],
              );
            },
            decoration: textInputDecoration,
            enableFeedback: true,
            menuMaxHeight: 300,
            iconSize: 18,
            printCountryName: false,
            onCountrySelected: widget.onChanged,
          ),
        ),
      ],
    );
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    unfortunatelly is not what I need, here a full code where demostrate that I cannot update the second CountryDropDown based on the first one, meanwhile the 2nd TextFormField (that is just a reference) is changing, I guess that's a CountryDropDown issue... or not? I've tried everything see next example:

    import 'dart:developer';
    import 'package:flutter/material.dart';
    import 'package:flutter_multi_formatter/formatters/phone_input_formatter.dart';
    import 'package:flutter_multi_formatter/widgets/country_dropdown.dart';
    import 'package:flutter_multi_formatter/widgets/country_flag.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    GlobalKey<CountryDropDownCustomState> countryDropDownCustomKey = GlobalKey<CountryDropDownCustomState>();
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      PhoneCountryData? _initialCountryData;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Expanded(
                  child: CountryDropDownCustom(
                key: const Key('first'),
                initialCountryData: PhoneCodes.getPhoneCountryDataByCountryCode('US')!,
                onChanged: (code) {
                  setState(() {
                    countryDropDownCustomKey.currentState?.updateValue(code);
                  });
                },
              )),
              Expanded(
                child: CountryDropDownCustom(
                  key: countryDropDownCustomKey,
                  initialCountryData: _initialCountryData,
                  onChanged: (code) {
                    setState(() {
                      _initialCountryData = code;
                    });
                  },
                ),
              ),
            ],
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    class CountryDropDownCustom extends StatefulWidget {
      CountryDropDownCustom({super.key, this.initialCountryData, required this.onChanged});
      PhoneCountryData? initialCountryData;
      final ValueChanged<PhoneCountryData> onChanged;
    
      @override
      State<CountryDropDownCustom> createState() => CountryDropDownCustomState();
    }
    
    class CountryDropDownCustomState extends State<CountryDropDownCustom> {
      PhoneCountryData? _initialCountryCode;
      late TextEditingController countryCode;
    
      void updateValue(PhoneCountryData? newValue) {
        setState(() {
          log('updating... ${newValue!.countryCode ?? ''}');
          if (newValue?.countryCode != null) {
            _initialCountryCode = newValue;
            countryCode.text = newValue.countryCode ?? ''; //this is actually working
          }
          log('new value ${_initialCountryCode?.countryCode ?? ''}');
        });
      }
    
      @override
      void initState() {
        _initialCountryCode = widget.initialCountryData;
        countryCode = TextEditingController(text: _initialCountryCode?.countryCode?.toString() ?? '');
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Row(
          children: [
            //this is here just as a reference to see if the newValue is updated;
            Expanded(
                flex: 1,
                child: TextFormField(
                  controller: countryCode,
                )),
            const SizedBox(
              width: 5,
            ),
            Expanded(
              flex: 4,
              child: CountryDropdown(
                initialCountryData: _initialCountryCode,
                selectedItemBuilder: (phoneCountryData) {
                  return Row(
                    children: [
                      Padding(
                        padding: const EdgeInsets.only(right: 10.0),
                        child: CountryFlag(
                          height: 20,
                          width: 30,
                          countryId: phoneCountryData.countryCode!,
                        ),
                      ),
                      Flexible(
                        child: Text(
                          '+${phoneCountryData.phoneCode} - ${phoneCountryData.country}',
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ],
                  );
                },
                listItemBuilder: (phoneCountryData) {
                  return Row(
                    children: [
                      Padding(
                        padding: const EdgeInsets.only(right: 2.0),
                        child: CountryFlag(
                          height: 20,
                          width: 30,
                          countryId: phoneCountryData.countryCode!,
                        ),
                      ),
                      Flexible(
                        child: Text(
                          '+${phoneCountryData.phoneCode} - ${phoneCountryData.country}',
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ],
                  );
                },
                enableFeedback: true,
                menuMaxHeight: 300,
                iconSize: 18,
                printCountryName: false,
                onCountrySelected: widget.onChanged,
              ),
            ),
          ],
        );
      }
    }
    

  2. Your code requires two changes

    1. Assign TextEditingController controller:
     void updateValue(PhoneCountryData? newValue) {
        countryCode.text = _initialCountryCode?.countryCode?.toString() ?? '';
        if (mounted) {
          setState(() {
            _initialCountryCode = newValue;
          });
        }
      }
    
    1. Update local controller once country selection changes:
    CountryDropdown(
                initialCountryData: _initialCountryCode,
                selectedItemBuilder: (phoneCountryData) {
                  return Row(
                    children: [
                      Padding(
                        padding: const EdgeInsets.only(right: 10.0),
                        child: CountryFlag(
                          height: 20,
                          width: 30,
                          countryId: phoneCountryData.countryCode!,
                        ),
                      ),
                      Flexible(
                        child: Text(
                          '+${phoneCountryData.phoneCode} - ${phoneCountryData.country}',
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ],
                  );
                },
                listItemBuilder: (phoneCountryData) {
                  return Row(
                    children: [
                      Padding(
                        padding: const EdgeInsets.only(right: 2.0),
                        child: CountryFlag(
                          height: 20,
                          width: 30,
                          countryId: phoneCountryData.countryCode!,
                        ),
                      ),
                      Flexible(
                        child: Text(
                          '+${phoneCountryData.phoneCode} - ${phoneCountryData.country}',
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ],
                  );
                },
                decoration: textInputDecoration,
                enableFeedback: true,
                menuMaxHeight: 300,
                iconSize: 18,
                printCountryName: false,
                onCountrySelected: (newSelection) {
                  updateValue(newSelection);
                  widget.onChanged(newSelection);
                },
              )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search