How can I make dynamic text fields - flutter

I'm working on mathematics app. Currently I'm working on matrices. I want when user select dimension of matrix then on the next screen text fields with same dimension appears.
And how can I handle TextEditing controllers for each text field?
Here is how I'm taking matrix dimension from user
I made a simple text fields to take input from user
class Matrice extends StatelessWidget {
Matrice({Key? key}) : super(key: key);
final controller = Get.find<MatricesController>();
#override
Widget build(BuildContext context) {
return Container(
// color: Colors.green,
// height: 50.0,
width: double.infinity,
child: Row(
children: [
Text(
'[',
style: AppTextStyle.kBlackBold
.copyWith(fontSize: 80.sp, fontWeight: FontWeight.w300),
),
MathsField(
controller: controller.a11,
),
SizedBox(
width: 15.0,
),
MathsField(
controller: controller.a12,
),
Text(
']',
style: AppTextStyle.kBlackBold
.copyWith(fontSize: 80.sp, fontWeight: FontWeight.w300),
),
Text(
'+',
style: AppTextStyle.kBlackBold
.copyWith(fontSize: 80.sp, fontWeight: FontWeight.w300),
),
Text(
'[',
style: AppTextStyle.kBlackBold
.copyWith(fontSize: 80.sp, fontWeight: FontWeight.w300),
),
MathsField(
controller: controller.a21,
),
SizedBox(
width: 15.0,
),
MathsField(
controller: controller.a22,
),
Text(
']',
style: AppTextStyle.kBlackBold
.copyWith(fontSize: 80.sp, fontWeight: FontWeight.w300),
),
],
),
);
}
}
The output looks like this
And made controller for each textfield
TextEditingController a11 = TextEditingController();
TextEditingController a12 = TextEditingController();
TextEditingController a21 = TextEditingController();
TextEditingController a22 = TextEditingController();
Thanks :)

I made a simple example that you can view on DartPad: Matrix Example
Simply, you need to write the logic for creating text fields with controllers for each cell of the Matrix. This will translate into a List<List<TextEditingController>> based on a Matrix custom definition (i.e. has the number of rows and number of columns).
I see in your example that you're creating the controllers elsewhere (outside the widget tree). I'm not sure if this is the approach you would want to take. It's better to manage the Matrix data because that's what you're interested in. Given the data at hand, you can rebuild the matrix as shown below on MatrixPage. This will also allow you to save the data and use it else where (see: printMatrix method on the page, you can do the same to export the data).
The code for reference:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
),
body: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
MatrixOption(matrix: Matrix(1, 1)),
MatrixOption(matrix: Matrix(2, 2)),
MatrixOption(matrix: Matrix(3, 3)),
],
),
);
}
}
class Matrix {
final int rows;
final int columns;
const Matrix(this.rows, this.columns);
}
class MatrixOption extends StatelessWidget {
final Matrix matrix;
const MatrixOption({
Key? key,
required this.matrix,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return Scaffold(
appBar: AppBar(),
body: MatrixPage(matrix: matrix),
);
},
),
);
},
child: Container(
height: 50,
width: 100,
margin: const EdgeInsets.all(8),
color: Colors.orange,
child: Center(child: Text('${matrix.rows}' 'x' '${matrix.columns} Matrix ')),
),
);
}
}
class MatrixPage extends StatefulWidget {
final Matrix matrix;
const MatrixPage({
Key? key,
required this.matrix,
}) : super(key: key);
#override
State<MatrixPage> createState() => _MatrixPageState();
}
class _MatrixPageState extends State<MatrixPage> {
// List of lists (outer list is the rows, inner list is the columns)
final controllers = <List<TextEditingController>>[];
late final rows = widget.matrix.rows;
late final columns = widget.matrix.columns;
#override
void initState() {
super.initState();
createControllers();
}
void createControllers() {
for (var i = 0; i < rows; i++) {
controllers.add(List.generate(columns, (index) => TextEditingController(text: '0')));
}
}
void printMatrix() {
final strings = <List<String>>[];
for (var controllerRow in controllers) {
final row = controllerRow.map((e) => e.text).toList();
strings.add(row);
}
print(strings);
}
#override
void dispose() {
for (var controllerRow in controllers) {
for (final c in controllerRow) {
c.dispose();
}
}
super.dispose();
}
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
controllers.length,
(index1) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
controllers[index1].length,
(index2) => Center(
child: MatrixField(
controller: controllers[index1][index2],
),
),
),
),
),
),
TextButton(
onPressed: printMatrix,
child: const Text('Print Matrix'),
)
],
),
);
}
}
class MatrixField extends StatelessWidget {
final TextEditingController controller;
const MatrixField({
Key? key,
required this.controller,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return SizedBox(
height: 50,
width: 50,
child: TextField(
controller: controller,
),
);
}
}
Let me know if you've any questions about the code.

Related

How to have an onTap gesture multiple levels below effect a top level String Variable?

I've created a stateful Widget as my main page with a String variable, textToDisplay.
import 'package:flutter/material.dart';
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
String textToDisplay = 'Choose option';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Text(
'$textToDisplay',
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 20,
),
Choices(onTap: (){setState(() {
textToDisplay =
});},),
],
),
),
);
}
}
I have then created a stateless widget in another dart file called Choices().
class Choices extends StatelessWidget {
Choices({required this.onTap});
final VoidCallback? onTap;
#override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 20,
),
Buttons(text: 'Option A', onTap: onTap),
SizedBox(
height: 10,
),
Buttons(text: 'Option B', onTap: onTap),
],
);
}
}
and in this are 2 stateless widget buttons which have the ontap gesture.
class Buttons extends StatelessWidget {
Buttons({required this.text, required this.onTap});
final String text;
final VoidCallback? onTap;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Container(
color: Colors.green,
width: 100,
height: 40,
child: Text(
text,
),
),
);
}
}
I can pass the onTap gesture up the tree but what I need to do is when a button is pressed, it updates the variable, textToDisplay to display option A or Option B, depending on which button has been pressed.
I thought i could do this with a stateless widget (Choices()) because the data isn't chageing it is only being read
any help would be greatly appreciated.
One way of updating the top-level string is the create your own Callback using ValueChanged.
Here is a complete working example:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MainPage(),
),
),
);
}
}
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
String textToDisplay = 'Choose option';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Text(
textToDisplay,
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 20,
),
Choices(
onTap: (val) {
setState(() {
textToDisplay = val;
});
},
),
],
),
),
);
}
}
class Choices extends StatelessWidget {
Choices({required this.onTap});
final ValueChanged? onTap;
#override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 20,
),
Buttons(
text: 'Option A',
onTap: onTap,
),
SizedBox(
height: 10,
),
Buttons(text: 'Option B', onTap: onTap),
],
);
}
}
class Buttons extends StatelessWidget {
Buttons({required this.text, required this.onTap});
final String text;
final ValueChanged? onTap;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
if (onTap != null) {
onTap!(text);
}
},
child: Container(
color: Colors.green,
width: 100,
height: 40,
child: Text(
text,
),
),
);
}
}
you can use function with parameter
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
String textToDisplay = 'Choose option';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Text(
textToDisplay,
style: const TextStyle(fontSize: 20),
),
const SizedBox(
height: 20,
),
Choices(
onTap: (text) {
_chageText(text);
},
),
],
),
),
);
}
void _chageText(String text) {
setState(() {
textToDisplay = text;
});
}
}
class Choices extends StatelessWidget {
const Choices({super.key, required this.onTap});
final Function(String text) onTap;
#override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 20,
),
Buttons(text: 'Option A', onTap: () => onTap('Option A')),
const SizedBox(
height: 10,
),
Buttons(text: 'Option B', onTap: () => onTap('Option B')),
],
);
}
}
class Buttons extends StatelessWidget {
const Buttons({super.key, required this.text, required this.onTap});
final String text;
final VoidCallback? onTap;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Container(
color: Colors.green,
width: 100,
height: 40,
child: Text(
text,
),
),
);
}
}

I have a tab bar with 4 tabs, i wants to validate all the tabs data from main class? how to achieve it in flutter with Provider

Class A has 4 tabs, each tab has its own classes and fields, is there a elegant way to validate all the classes/tabs from Class A using Provider architecture.
Take a look at the official tutorial documentation. It's going to explain step by step how to create a model that shares states between other widgets.
I've also made the prototype below and a live demo on DartPad to help you out with your exact problem.
Data
A
B
Summary
No Data
With Data
Below is the code from DartPad as a minimum-reproducible-example. There is the Model provider where the data resides for every widget to access it. The classes A, B, and Summary each one consumes the Model data using the Consumer<Model>. Every time the Model changes it notifies all consumers (the listeners) of the change and then the widgets can be updated with the new data.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
enum BEnum {
test1,
test2,
}
class Model extends ChangeNotifier {
String _aText = '';
BEnum? _bEnum;
String get aText => _aText;
BEnum? get bEnum => _bEnum;
setText(String text) {
_aText = text;
notifyListeners();
}
setBEnum(BEnum? bEnum) {
_bEnum = bEnum;
notifyListeners();
}
}
void main() {
runApp(MultiProvider(providers: [
ChangeNotifierProvider(create: (_) => Model()),
], child: const MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _selectedIndex = 0;
final _tabs = [
const A(),
const B(),
const Summary(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(24),
child: Center(child: _tabs[_selectedIndex]),
),
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(icon: Icon(Icons.abc), label: 'A'),
BottomNavigationBarItem(icon: Icon(Icons.bolt), label: 'B'),
BottomNavigationBarItem(icon: Icon(Icons.list), label: 'Summary'),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
}
class A extends StatelessWidget {
const A({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
const Text(
'A',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
Consumer<Model>(
builder: (context, model, child) {
return TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'A',
),
onChanged: (value) => model.setText(value),
);
},
)
],
);
}
}
class B extends StatelessWidget {
const B({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Consumer<Model>(
builder: (context, model, _) {
return Column(
children: [
const Text(
'B',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
Expanded(
child: ListView.builder(
itemCount: BEnum.values.length,
itemBuilder: (context, index) {
final bEnum = BEnum.values[index];
return RadioListTile<BEnum?>(
title: Text(bEnum.name),
groupValue: model.bEnum,
value: bEnum,
onChanged: (value) => model.setBEnum(value),
);
},
),
),
],
);
},
);
}
}
class Summary extends StatelessWidget {
const Summary({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Consumer<Model>(
builder: (context, model, _) {
return Column(
children: [
const Text(
'Summary',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
Row(
children: [
const Text('A text: ',
style: TextStyle(fontWeight: FontWeight.bold)),
Text(model.aText),
],
),
Row(
children: [
const Text('B selection: ',
style: TextStyle(fontWeight: FontWeight.bold)),
Text(model.bEnum?.name ?? 'None'),
],
),
],
);
},
);
}
}

How can I pass data from a TextFieldInput to another Page with Provider

I want to pass the Data (String) from a TextField to a second Page with Provider after I clicked the Button.
Here is my code
Update your name_provider class
class NameProvider extends ChangeNotifier {
String _name = "";
String get getName => _name;
saveName(String name) {
_name = name;
notifyListeners();
}
}
The name variable was made private to avoid getting wrong result while calling the function.
Now this edit was made to main.dart file
class _MyHomePageState extends State<MyHomePage> {
String name = "";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Please enter your name',
),
TextField(
onSubmitted: (value) {
setState(() {
Provider.of<NameProvider>(context).saveName(value);
});
},
onChanged: (value) {
setState(() {
name = value;
});
},
),
Text("Name: $name"),
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SecondPage(),
),
);
},
child: const Text("To Second Page"),
),
],
),
),
),
);
}
}
Now getting name in SecondPage:
class SecondPage extends StatelessWidget {
const SecondPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Second Page"),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Name:",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
Text(
Provider.of<NameProvider>(context).getName,
style: TextStyle(fontSize: 32),
),
],
),
),
),
);
}
}
If there is some sort of expected string but got... error, replace getName with '${Provider.of<NameProvider>(context).getName}'
Let us know if this solution works
First of all, in the main.dart file at line 70, do this:
Provider.of<NameProvider>(context).saveName(name);
and then on the second page where you want to use this Provider.of<NameProvider>(context).name;
Here is the full working code.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProviderCheck extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => NameProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Provider Problem'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String name = "";
//it will store data in typed in textfield
final TextEditingController _textEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Please enter your name',
),
TextField(
controller: _textEditingController,//texteditingcontroller set to textfield
onSubmitted: (value) {
setState(() {
name = value;
});
},
onChanged: (value) {
setState(() {
name = value;
});
},
),
Text("Name: $name"),
TextButton(
onPressed: () {
//saveName method called using provider and name saved.
Provider.of<NameProvider>(context, listen: false)
.saveName(_textEditingController.text);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SecondPage(),
),
);
},
child: const Text("To Second Page"),
),
],
),
),
),
);
}
}
class NameProvider extends ChangeNotifier {
String name = "";
String get getName => name;
//name1 value will set to name variable
saveName(String name1) {
name = name1;
notifyListeners();
}
}
class SecondPage extends StatelessWidget {
const SecondPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Second Page"),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//using provider, we can access the saved name
Text(
"Name:${Provider.of<NameProvider>(context, listen: false).getName}",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
Text(
//TODO: Name should be displayed here
"Name",
style: TextStyle(fontSize: 32),
),
],
),
),
),
);
}
}
if you prefer to use provider for that purpose,
edit your provider saveName Function to :
saveName(String _name) {
name = _name;
notifyListeners();
}
in SecondPage() add
your provider to the build method like this :
class SecondPage extends StatelessWidget {
const SecondPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final nameProvider = Provider.of< NameProvider>(context);
then get your string value by calling :
Text(
"Name: ${nameProvider.name}",
style : ....

How to change variable with getx?

As in the codes I mentioned below, my question is actually simple, but I couldn't find a simple answer on the internet. All the sources I found are going through the same example. There is no simple explanation, but there is good stackoverflow. Let me ask my question without further ado.
I can specify a variable in getx and print that variable on other pages. What I want to do now is I want to change the getx variable in the main file, how can I do that?
I'm posting the wrong version of the code I want to do below for you to understand.
code in getx folder
class numcontroller extends GetxController {
var derece = 20.obs;
}
code is second page
numcontroller deneme = Get.put(numcontroller());
Container(
margin: const EdgeInsets.fromLTRB(27, 10, 0, 0),
child: Row(
children: [
Container(
margin: const EdgeInsets.fromLTRB(5, 0, 0, 0),
child: Text('${deneme.derece.value}',
style: const TextStyle(
fontSize: 45,
fontFamily: 'YesevaOne',
color: Color(0xFF2d4b70)),
),
),
The code I want to run in main.dart
derece = 20
or
derece = 30
When I change the degree manually on main.dart, I want it to change on the second page as well.
EDİTİNG
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:teemapp4/Controller/switch_controller.dart';
import 'routes/app_pages.dart';
import 'routes/app_routes.dart';
import 'themes/app_theme.dart';
//0xFF2d4b70
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetMaterialApp(
initialRoute: AppRoutes.DASHBOARD,
getPages: AppPages.list,
debugShowCheckedModeBanner: false,
theme: AppTheme.light,
darkTheme: AppTheme.dark,
themeMode: ThemeMode.system,
);
}
}
this is my main.dart code but i am using a bottombar i made with getx. I'm looking for how to change the data in that file through this code.
I don't think So you need to update your main.dart file.
You can add a button on your first page to update values like:
firstPage.dart
class FirstPage extends StatelessWidget {
FirstPage({Key? key}) : super(key: key);
NumController numController = Get.put(NumController());
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
ElevatedButton(
onPressed: () {
numController.updateDerece(30);
},
child: Text(
"Update Value",
),
),
ElevatedButton(
onPressed: () {
Get.to(() => SecondPage());
},
child: Text("Go To Second Screen"),
),
],
),
),
);
}
}
secondPage.dart
class SecondPage extends StatelessWidget {
SecondPage({Key? key}) : super(key: key);
NumController numController = Get.find<NumController>();
#override
Widget build(BuildContext context) {
return Container(
child: Text(
numController.derece.toString(),
),
);
}
}
Or You can directly update the value on your second page like:
secondPage.dart
class SecondPage extends StatelessWidget {
SecondPage({Key? key}) : super(key: key);
NumController numController = Get.put(NumController());
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
ElevatedButton(
onPressed: () {
//Any Number You can pass in Function
numController.updateDerece(30);
},
child: Text(
"Update Value",
),
),
Obx(
() => Container(
child: Text(
numController.derece.toString(),
),
),
),
],
),
),
);
}
}
numController.dart
import 'package:get/get.dart';
class NumController extends GetxController {
var _derece = 20.obs;
int get derece => _derece.value;
void updateDerece(int value) {
_derece.value = value;
}
}
Try using this way. And update your derece variable value using updateDerece method.
var _derece = 20.obs;
double get derece => _derece.value;
void updateDerece(double value) {
_derece.value = value;
}
////
Obx(() {
return Container(
margin: const EdgeInsets.fromLTRB(27, 10, 0, 0),
child: Row(
children: [
Container(
margin: const EdgeInsets.fromLTRB(5, 0, 0, 0),
child: Text(
'${deneme.derece}',
style: const TextStyle(
fontSize: 45,
fontFamily: 'YesevaOne',
color: Color(0xFF2d4b70)),
),
),
],
),
);
})

Failed assertion:'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) return item.value == value;}).length == 1'

class DropDown extends StatefulWidget {
const DropDown({
this.data,
this.hint,
Key key,
}) : super(key: key);
final List<String> data;
final String hint;
#override
_DropDownState createState() => _DropDownState();
}
String _chosenValue1;
class _DropDownState extends State<DropDown> {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
width: 250,
padding: const EdgeInsets.all(0.0),
child: DropdownButton<String>(
iconSize: 30,
isExpanded: true,
value: _chosenValue1,
//elevation: 5,
items: widget.data.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
hint: Text(
widget.hint,
style: TextStyle(
color: Colors.black,
fontSize: 13,
fontWeight: FontWeight.w600,
),
),
onChanged: (String value) {
setState(() {
_chosenValue1 = value;
});
},
),
),
);
}
}
DropDown(
data: [
'Non-Blanchable',
'Partial thickness skin',
'Full thickness skin loss involving damage or necrosis',
'Obscured by necrosis'
],
hint: 'Assessment',
),
DropDown(
data: [
'Indistinct, diffuse,none ',
'Distinct,outline clearly'
],
hint: 'Assessment',
),
i have been stuck on this problem for a while now, When i have the same data inside the data it works however all the dropdown would become the same, I want to be able to have different data for different dropdown , but when i do so the error is caused and i cant figure out whats wrong with it
import 'package:flutter/material.dart';
class DropDown extends StatefulWidget {
DropDown({
this.data,
this.hint,
this.initialValue,
Key? key,
}) : super(key: key);
final List<String>? data;
final String? hint;
final String? initialValue;
String chosenValue1 = "";
#override
_DropDownState createState() => _DropDownState();
}
class _DropDownState extends State<DropDown> {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
width: 250,
padding: const EdgeInsets.all(0.0),
child: DropdownButton<String>(
iconSize: 30,
isExpanded: true,
value: widget.initialValue!.isEmpty ? null : widget.initialValue!,
//elevation: 5,
items: widget.data!.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
hint: Text(
widget.hint!,
style: const TextStyle(
color: Colors.black,
fontSize: 13,
fontWeight: FontWeight.w600,
),
),
onChanged: (value) {
setState(() {
widget.chosenValue1 = value!;
});
},
),
),
);
}
}
import 'package:flutter/material.dart';
import 'dropdown.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropDown(
data: const [
'Non-Blanchable',
'Partial thickness skin',
'Full thickness skin loss involving damage or necrosis',
'Obscured by necrosis'
],
hint: 'Assessment',
initialValue: "Non-Blanchable",
),
DropDown(
data: const [
'Indistinct, diffuse,none',
'Distinct,outline clearly'
],
hint: 'Assessment',
initialValue: "",
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Use the above code it will fix ur error
I tried running your code and, after making your data and hint required params and moving the chosenValue variable inside your _DropDownState, it works perfectly fine. Can you maybe share some steps with how to reproduce the error that you're seeing, because I see two different dropdowns with values I can select independently of each other.
As per your description of how to reproduce the error, I've tried adding navigation between two screens, but it still all works as intended.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Dropdowns(),
);
}
}
class Dropdowns extends StatelessWidget {
const Dropdowns();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.all(40),
child: Column(
children: [
Text('This is the first screen'),
DropDown(
data: [
'Non-Blanchable',
'Partial thickness skin',
'Full thickness skin loss involving damage or necrosis',
'Obscured by necrosis'
],
hint: 'Assessment',
),
DropDown(
data: ['Indistinct, diffuse,none ', 'Distinct,outline clearly'],
hint: 'Assessment',
),
ElevatedButton(
child: Text('Go to second screen'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SecondScreen(),
),
);
},
),
],
),
),
);
}
}
class DropDown extends StatefulWidget {
const DropDown({
required this.data,
required this.hint,
Key? key,
}) : super(key: key);
final List<String> data;
final String hint;
#override
_DropDownState createState() => _DropDownState();
}
class _DropDownState extends State<DropDown> {
String? _chosenValue1;
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
width: 250,
padding: const EdgeInsets.all(0.0),
child: DropdownButton<String>(
iconSize: 30,
isExpanded: true,
value: _chosenValue1,
//elevation: 5,
items: widget.data.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
hint: Text(
widget.hint,
style: TextStyle(
color: Colors.black,
fontSize: 13,
fontWeight: FontWeight.w600,
),
),
onChanged: (String? value) {
setState(() {
_chosenValue1 = value;
});
},
),
),
);
}
}
class SecondScreen extends StatelessWidget {
const SecondScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SECOND SCREEN'),
),
body: Padding(
padding: EdgeInsets.all(40),
child: Column(
children: [
Text('This is the second screen'),
DropDown(
data: [
'Non-Blanchable',
'Partial thickness skin',
'Full thickness skin loss involving damage or necrosis',
'Obscured by necrosis'
],
hint: 'Assessment',
),
DropDown(
data: ['Indistinct, diffuse,none ', 'Distinct,outline clearly'],
hint: 'Assessment',
),
],
),
),
);
}
}
onChanged: (String value) {
setState(() {
_chosenValue = value;
selcat = null; use dropdown as category
_chosenValue == null
? Container()
: _chosenValue == "hi"
? _hi()
: _chosenValue == "hello"
? _hello()
: Container(),