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.)
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;
}