I'm calculating total on the base of quantity when I select quantity from dropdown it gets changed but total amount Textformfield remain same and when I debug the code I get updated amount in setState method but does not reflect on the UI and I'm also updating total from another method in that method it is working.

 class _ProductDetailsPageState extends State<ProductDetailsPage> {

  List _quantity = ["1", "2", "3", "4", "5"];
  List<DropdownMenuItem<String>> _dropDownQuantity;

  String _currentQuantity;
  String _productprice;
  double _taxrateamt;
  double _taxper = 0.0;
  String _producttotal;
  int _productqty;
  double _discount = 3.0;
  String _productname;

  List<DropdownMenuItem<String>> getDropDownQuantity() {
    List<DropdownMenuItem<String>> items = new List();
    for (String city in _quantity) {
      items.add(new DropdownMenuItem(
          value: city,
          child: new Text(
            city,
            style:
                TextStyle(color: MyColors.colorPrimary, fontFamily: 'semibold'),
          )));
    }
    return items;
  }

  @override
  void initState() {
    super.initState();

    _dropDownQuantity = getDropDownQuantity();
    _currentQuantity = _dropDownQuantity[0].value;
  }

  Container rateAndTotal( String value) {
    return Container(
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Expanded(
                flex: 1,
                child: Container(
                  child: TextFormField(
                    style: TextStyle(
                        fontFamily: 'medium', color: MyColors.colorPrimaryDark),
                    keyboardType: TextInputType.number,
                    enabled: false,
                    textInputAction: TextInputAction.done,
                    initialValue: '${value}',
                    decoration: InputDecoration(
                        border: InputBorder.none, hintText: '$value'),),),),],),],),);}

  Container quantity() {
    return Container(
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Expanded(
                flex:1,
                child: Container(
                     child: DropdownButtonHideUnderline(
                      child: DropdownButton(
                        value: _currentQuantity,
                        items: _dropDownQuantity,
                        onChanged: changedDropDownQuantity,),)),),],),],),);}

  @override
  Widget build(BuildContext context) {

        MediaQueryData queryData;
        queryData = MediaQuery.of(context);
        double width = queryData.size.width;
        double height = queryData.size.height;

        return new Container(
          height: double.infinity,
          decoration: BoxDecoration(color: Colors.grey[200]),
          child: SingleChildScrollView(
            child: Container(
              padding: EdgeInsets.all(height * 0.020),
              child: Column(
                children: <Widget>[
                  quantity(),
                  rateAndTotal( '${_productprice}'),
                ],
              ),
            ),
          ),
        );
  }

  void changedDropDownQuantity(String selected_quantity) {
    setState(() {
      _currentQuantity = selected_quantity;
      // _producttotal=getProductTotal(_productprice,_currentQuantity);
    });

    setState(() {
      _producttotal=getProductTotal(_productprice,_currentQuantity);
    });

  }

  String getProductTotal(String productprice, String _currentQuantity) {
    try {

      double sprice = 0.0;
      double total = double.parse(productprice);
      double taxrate = _taxrateamt;
      double qty = double.parse(_currentQuantity);

      return _producttotal =
          (((total + taxrate + sprice) - _discount) * qty).toString();
    } catch (e) {
      debugPrint('PRODUCT TOTAl EXC.:--${e}');

      return _producttotal = productprice;
    }
  }
}

enter image description here


Solution 1: greyaurora

To fix this, replace the below line in your TextFormField:

initialValue: '$value',

with:

controller: TextEditingController(text: value),

or better yet:

// Define a controller in the State
class _ProductDetailsPageState extends State<ProductDetailsPage> {
  TextEditingController _controller = TextEditingController(text: value);

  ...
  // Then bind that controller to your TextFormField, replacing initialValue
    child: TextFormField(
      controller: _controller,

  ...

  // Then change the .text property of that controller when you want it to update
  setState(() => _controller.text = value);

initialValue is only used to set what the very first value of the TextFormField will be when the State is first initialised, and State is preserved through rebuilds so overriding it will never cause the text to change.

Overriding the TextEditingController completely each time or defining a TextEditingController and changing the .text property will properly pass the change to the State of the field and update your value.


Solution 2: Timur Turbil

Another case; if you use dropdownbutton on pop-up, you need to use StatefulBuilder. Here is the reference; How to refresh an AlertDialog in Flutter?