skip to Main Content

I have the following code where I am trying to get the contents of the TextField next to Result Text in the UI to update automatically based on the changed item in the DropdownMenu of this Flutter app.

Code:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @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'),
    );
  }
}

const List<String> list = <String>[
  "A",
  "B",
  "C",
];

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late final TextEditingController firstController;
  late final TextEditingController controllerResult;
  late String dropdownValue = list.first;

  @override
  void initState() {
    super.initState();
    firstController = TextEditingController();
    controllerResult = TextEditingController();
  }

  @override
  void dispose() {
    firstController.dispose();
    controllerResult.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    ComputeResult cr;

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Container(
        padding: const EdgeInsets.all(10.0),
        child: Column(
          children: [
            Row(
              children: [
                Expanded(
                  flex: 5,
                  child: TextField(
                    controller: firstController,
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      hintText: 'Value',
                    ),
                    keyboardType: TextInputType.number,
                    onChanged: (value) {
                      if (firstController.text.isNotEmpty) {
                        switch (dropdownValue) {
                          case "A":
                            controllerResult.text = "-1";
                            break;
                          case "B":
                            controllerResult.text = "-2";
                            break;
                          case "C":
                            cr = ComputeResult.named03(
                                double.parse(firstController.text));
                            controllerResult.text = cr.value01.toString();
                            break;
                        }
                      } else {
                        controllerResult.text = "";
                      }
                    },
                  ),
                ),
                Expanded(
                  flex: 5,
                  child: DropdownMenu<String>(
                    initialSelection: list.first,
                    onSelected: (String? value) {
                      setState(() {
                        dropdownValue = value!;
                      });
                    },
                    dropdownMenuEntries:
                        list.map<DropdownMenuEntry<String>>((String value) {
                      return DropdownMenuEntry<String>(
                          value: value, label: value);
                    }).toList(),
                  ),
                ),
              ],
            ),
            SingleChildScrollView(
              child: Column(
                children: [
                  Row(
                    children: [
                      Expanded(
                        flex: 5,
                        child: TextField(
                          readOnly: true,
                          controller: controllerResult,
                        ),
                      ),
                      Expanded(
                        flex: 5,
                        child: Text("Result"),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class ComputeResult {
  ComputeResult.named01(this.value01) {
    value02 = value01 + 100;
    value03 = value01 + 110;
  }
  ComputeResult.named02(this.value02) {
    value01 = value02 + 200;
    value03 = value02 + 210;
  }
  ComputeResult.named03(this.value03) {
    value01 = value03 + 300;
    value02 = value03 + 310;
  }
  double value01 = 0;
  double value02 = 0;
  double value03 = 0;
}

How can I implement that, could someone help? (Currently, after selecting a new item from DropdownMenu, the value does not update automatically, but only if we change the text of the TextField that is not readOnly, next to DropdownMenu in the UI.)

What I’ve tried: I have tried adding listener to the firstController as described in this answer, but that did not work.

Snapshots: (Currently on selection of new items on DdropdownMenu, those supposed to be updated in the TextField next to Results aren’t updated.)

snapshots_gif

2

Answers


  1. DropdownMenu essentially functions as a TextField, therefore, it supports the use of TextEditingController. So, all we need to do is to add a controller to DropdownMenu. Partial code is as follows:

    late final TextEditingController dropdownMenuController;
    
    @override
    void initState() {
      super.initState();
      dropdownMenuController = TextEditingController();
    }
    
    DropdownMenu<String>(
      controller: dropdownMenuController,
    

    In the onChanged event of the TextField you want to listen to, add the following code to change the content of the DropdownMenu. Partial code is as follows:

    onChanged: (value) {
      if (value.isNotEmpty && int.tryParse(value) == 1) {
        dropdownMenuController.text = "C";
      }
    

    example:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @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'),
        );
      }
    }
    
    const List<String> list = <String>[
      "A",
      "B",
      "C",
    ];
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      late final TextEditingController firstController;
      late final TextEditingController controllerResult;
      late final TextEditingController ropdownMenuController;
      late String dropdownValue = list.first;
    
      @override
      void initState() {
        super.initState();
        firstController = TextEditingController();
        controllerResult = TextEditingController();
        ropdownMenuController = TextEditingController();
      }
    
      @override
      void dispose() {
        firstController.dispose();
        controllerResult.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        ComputeResult cr;
    
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Container(
            padding: const EdgeInsets.all(10.0),
            child: Column(
              children: [
                Row(
                  children: [
                    Expanded(
                      flex: 5,
                      child: TextField(
                        controller: firstController,
                        decoration: const InputDecoration(
                          border: OutlineInputBorder(),
                          hintText: 'Value',
                        ),
                        keyboardType: TextInputType.number,
                        onChanged: (value) {
                          if(value.isNotEmpty&&int.tryParse(value)==1){
                            ropdownMenuController.text = "C";
                          }
    
                          if (firstController.text.isNotEmpty) {
                            switch (dropdownValue) {
                              case "A":
                                controllerResult.text = "-1";
                                break;
                              case "B":
                                controllerResult.text = "-2";
                                break;
                              case "C":
                                cr = ComputeResult.named03(
                                    double.parse(firstController.text));
                                controllerResult.text = cr.value01.toString();
                                break;
                            }
                          } else {
                            controllerResult.text = "";
                          }
                        },
                      ),
                    ),
                    Expanded(
                      flex: 5,
                      child: DropdownMenu<String>(
                        controller: ropdownMenuController,
                        initialSelection: list.first,
                        onSelected: (String? value) {
                          setState(() {
                            dropdownValue = value!;
                          });
                        },
                        dropdownMenuEntries:
                        list.map<DropdownMenuEntry<String>>((String value) {
                          return DropdownMenuEntry<String>(
                              value: value, label: value);
                        }).toList(),
                      ),
                    ),
                  ],
                ),
                SingleChildScrollView(
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: TextField(
                              readOnly: true,
                              controller: controllerResult,
                            ),
                          ),
                          Expanded(
                            flex: 5,
                            child: Text("Result"),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class ComputeResult {
      ComputeResult.named01(this.value01) {
        value02 = value01 + 100;
        value03 = value01 + 110;
      }
      ComputeResult.named02(this.value02) {
        value01 = value02 + 200;
        value03 = value02 + 210;
      }
      ComputeResult.named03(this.value03) {
        value01 = value03 + 300;
        value02 = value03 + 310;
      }
      double value01 = 0;
      double value02 = 0;
      double value03 = 0;
    }
    
    Login or Signup to reply.
  2. What you want is that when you select an item from the dropdownMenu, the textFiled should be updated. But that won’t happen. the value of the textFiled below will be updated only when you type in the above textFiled. To solve this, you can do the type above, create a separate function for the if condition in the Onchange method of the textFiled, and then call the created function in the Onselected method in the dropdownMenu.

    your code will be change like this :

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @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'),
        );
      }
    }
    
    const List<String> list = <String>[
      "A",
      "B",
      "C",
    ];
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      late final TextEditingController firstController;
      late final TextEditingController controllerResult;
      late String dropdownValue = list.first;
      //add this
      late ComputeResult cr;
    
      @override
      void initState() {
        super.initState();
        firstController = TextEditingController();
        controllerResult = TextEditingController();
      }
    
      @override
      void dispose() {
        firstController.dispose();
        controllerResult.dispose();
        super.dispose();
      }
    //create a function like this
      void changeResult (dropdownValue){
        if (firstController.text.isNotEmpty) {
          switch (dropdownValue) {
            case "A":
              controllerResult.text = "-1";
              break;
            case "B":
              controllerResult.text = "-2";
              break;
            case "C":
              cr = ComputeResult.named03(
                  double.parse(firstController.text));
              controllerResult.text = cr.value01.toString();
              break;
          }
        } else {
          controllerResult.text = "";
        }
      }
    
      @override
      Widget build(BuildContext context) {
        ComputeResult cr;
    
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Container(
            padding: const EdgeInsets.all(10.0),
            child: Column(
              children: [
                Row(
                  children: [
                    Expanded(
                      flex: 5,
                      child: TextField(
                        controller: firstController,
                        decoration: const InputDecoration(
                          border: OutlineInputBorder(),
                          hintText: 'Value',
                        ),
                        keyboardType: TextInputType.number,
                        onChanged: (value) {
                          //remove if condition
                          
                        },
                      ),
                    ),
                    Expanded(
                      flex: 5,
                      child: DropdownMenu<String>(
                        initialSelection: list.first,
                        onSelected: (String? value) {
                          //call the function
                          changeResult(value);
                        },
                        dropdownMenuEntries:
                            list.map<DropdownMenuEntry<String>>((String value) {
                          return DropdownMenuEntry<String>(
                              value: value, label: value);
                        }).toList(),
                      ),
                    ),
                  ],
                ),
                SingleChildScrollView(
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: TextField(
                              readOnly: true,
                              controller: controllerResult,
                            ),
                          ),
                          Expanded(
                            flex: 5,
                            child: Text("Result"),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class ComputeResult {
      ComputeResult.named01(this.value01) {
        value02 = value01 + 100;
        value03 = value01 + 110;
      }
      ComputeResult.named02(this.value02) {
        value01 = value02 + 200;
        value03 = value02 + 210;
      }
      ComputeResult.named03(this.value03) {
        value01 = value03 + 300;
        value02 = value03 + 310;
      }
      double value01 = 0;
      double value02 = 0;
      double value03 = 0;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search