How to change value on DropdownButton in onChange in Flutter - flutter

I am a beginner in the flutter I'm just learning flutter and I am stuck in this code how to solve this please help me?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Application',
home: book(),
);
}
}
class book extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return _bookstate();
}
}
class _bookstate extends State<book>{
String namebook = "";
var writter = ['A','B','C'];
var _currentItemSelected = 'A';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stateful Widget'),
),
body: Container(
margin: EdgeInsets.all(20.0),
child: Column(
children:<Widget> [
TextField(
onChanged: (String userInput){
setState(() {
namebook=userInput;
});
},
),
DropdownButton<String>(
items: writter.map((String dropDownStringItem){
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
onChanged: (String newValueSelected){
setState(() {
this._currentItemSelected = newValueSelected;
});
},
value: _currentItemSelected,
),
Text("Enter book name id $namebook",style: TextStyle(fontSize:20.0),),
],
),
),
);
}
}
and error show this message:
Error: The argument type 'void Function(String)' can't be assigned to the parameter type 'void Function(String?)?' because 'String?' is nullable and 'String' isn't.

You need to follow null safety rules, because your version supports null safety.
Simply change your code;
onChanged: (String? newValueSelected) {
setState(() {
this._currentItemSelected = newValueSelected!;
});
},
And I suggest check and learn what null safety is.

void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Book(),
);
}
}
class Book extends StatefulWidget {
const Book({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return _Bookstate();
}
}
class _Bookstate extends State<Book> {
String namebook = "";
var writter = ['A', 'B', 'C'];
var _currentItemSelected = 'A';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stateful Widget'),
),
body: Container(
margin: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
TextField(
onChanged: (String userInput) {
setState(() {
namebook = userInput;
});
},
),
DropdownButton<String>(
items: writter.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
onChanged: (String? newValueSelected) {
setState(() {
_currentItemSelected = newValueSelected!;
});
},
value: _currentItemSelected,
),
Text(
"Enter book name id $namebook",
style: const TextStyle(fontSize: 20.0),
),
],
),
),
);
}
}

Related

How to open DropDownButton on init page

i want to make a function for init openDropDown(); when page loaded or tap on other widget
I found this in stackoverfow
but its not working maybe its outdated. how can i achieve. with flutter 2.10
here is my dropdown
DropdownButton(
isExpanded: true,
value: selectedValue,
items: [
for (var i = 0; i < this.clients.length; i++)
DropdownMenuItem(
child: Text(this.clients[i]['name'].toString() +
' (' +
this.clients[i]['wallet'].toString() +
') '),
value: this.clients[i]['id'].toString())
],
onChanged: (String? newValue) {
setState(() {
selectedValue = newValue!;
});
},
),
You can take advantage of GlobalKey to get this job done... Also use SchedulerBinding because in initState key would be null so you won't be able to open DropDown from null key... here is the proper code how you do that task
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.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 DropDownButton',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey _dropdownButtonKey = GlobalKey();
final Intent _intent = const ActivateIntent();
// Initial Selected Value
String dropdownvalue = 'Item 1';
// List of items in our dropdown menu
var items = [
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5',
];
#override
void initState() {
super.initState();
SchedulerBinding.instance?.addPostFrameCallback((_) {
if (_dropdownButtonKey.currentContext != null) {
_dropdownButtonKey.currentContext?.visitChildElements((element) {
if (element.widget is Semantics) {
element.visitChildElements((element) {
if (element.widget is Actions) {
element.visitChildElements((element) {
Actions.invoke(element, _intent);
return;
});
}
});
}
});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DropdownButton(
autofocus: true,
key: _dropdownButtonKey,
isDense: true,
isExpanded: true,
value: dropdownvalue,
icon: const Icon(Icons.keyboard_arrow_down),
items: items.map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
});
},
),
],
),
),
);
}
}

The type 'DropDownField' is declared with 0 type parameters, but 1 type arguments were given

Widget locationList(String airportId) {
return Container(
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("Airports").doc(widget.airportId).collection("Locations").snapshots(),
builder: (context, snapshot) {
if(snapshot.data == null){
return Container();
} else {
List<DropdownMenuItem<String>> locationItem = [];
for(int i=0;i<snapshot.data!.docs.length;i++){
DocumentSnapshot data = snapshot.data!.docs[i];
locationItem.add(
DropdownMenuItem<String>(
child: Text(
data["Location Name"],
),
value: "${data["Location Name"]}",
)
);
}
return Form(
key: _formKey,
child: Container(
alignment: Alignment.center,
height: 55,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.black,width: 2)
),
child: DropdownButtonHideUnderline(
child: DropDownField<DropdownMenuItem<String>>(
value: value,
required: true,
items: locationItem,
enabled: true,
strict: false,
itemsVisibleInDropdown: 5,
onValueChanged: (value) {
setState(() {
this.value = value!;
locationId = value;
** print(value);**
print(locationId);
});
},
),
),
),
);
}
},
),
);
}
You should use "DropdownButton" or "DropdownButtonFormField" instead of "DropDownField".
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButtonHideUnderline(
child:DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),);
}
}
This question is old but probably some newbie like me can get help from this answer.
In my case I declared widget as
class CandleStickChartWidget extends StatefulWidget<CandleStikState>
instead of
class CandleStickChartWidget extends StatefulWidget
Correcting to the second line fixed it.

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(),

Why can't I display a list in rows in dropdown button in Flutter?

I want to show an icon and text as each item in a dropdown menu.
According to this answer https://stackoverflow.com/a/65831827/7870443 I tried. But my code is not working. I see an underline and dropdown button. But not clickable.
This is what I got.
I see an underline and dropdown button. But not clickable.
Below is the code I tried from that link
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/style.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String dropdownValue = 'Hillary';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: DropdownButton<String>(
items: <String>['Hillary', 'Joe', 'Felix', 'Monica'].map((name) {
return DropdownMenuItem<String>(
value: name,
// Your row here:
child: Row(
children: [
Icon(Icons.person),
Text(name),
],
),
);
}).toList(),
onChanged: (selectedName) {
setState(() {
dropdownValue = selectedName;
});
},
),
)
);
}
}
just set value for DropdownButton like code below:
String dropdownValue = 'Hillary';
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
appBar: AppBar(
title: Text('widget.title'),
),
body: Center(
child: DropdownButton<String>(
value: dropdownValue,
items: <String>['Hillary', 'Joe', 'Felix', 'Monica'].map((name) {
return DropdownMenuItem<String>(
value: name,
// Your row here:
child: Row(
children: [
Icon(Icons.person),
Text(name),
],
),
);
}).toList(),
onChanged: (selectedName) {
setState(() {
dropdownValue = selectedName;
});
},
),
));
}
for Change icon one way is using Map like code below:
String dropdownValue = 'Hillary';
Map<String, IconData> map = {
'Hillary': Icons.language,
'Joe': Icons.person,
'Felix': Icons.print,
'Monica': Icons.title
};
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
appBar: AppBar(
title: Text('widget.title'),
),
body: Center(
child: DropdownButton<String>(
value: dropdownValue,
items: <String>['Hillary', 'Joe', 'Felix', 'Monica'].map((name) {
return DropdownMenuItem<String>(
value: name,
// Your row here:
child: Row(
children: [
Icon(map[name]),
Text(name),
],
),
);
}).toList(),
onChanged: (selectedName) {
setState(() {
dropdownValue = selectedName;
});
},
),
));
}

flutter - creating dropdown button with data from props

i'm learning flutter for some time and i have a problem that i dont know how to solve.
I'm trying to create a dropdown button with data that I pass from the parent,data is a list of words like ['work','hobby','social'] etc.
My problem is the dropdown button after changing the value is still showing the initial one i think the problem is in the place when i initialize the "dropdownValue" because i do it in a build method but i cant acces properties from outside of that widget.
class TaskSheet extends StatefulWidget {
#override
_TaskSheetState createState() => _TaskSheetState();
final List categories;
TaskSheet(this.categories);
**// HERE I RECIVE THE LIST**
}
class _TaskSheetState extends State<TaskSheet> {
String dropdownValue;
// I CANT ASSIGN VALUE HERE BECAUSE USING widget.categories DONT WORK HERE AND IT MUST BE INSIDE BUILD METHOD
#override
Widget build(BuildContext context) {
var categoriesList = widget.categories
.map(
(category) => DropdownMenuItem(
value: category.title,
child: Text(category.title),
),
)
.toList();
dropdownValue = categoriesList[0].value; // THIS VALUE ALWAYS STAY THE SAME
return BottomSheet(
builder: (context) => Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 16),
child: Column(
children: [
Text('Add new task'),
TextField(
decoration: InputDecoration(labelText: 'What you wanna do?'),
),
DropdownButton(
icon: Icon(Icons.keyboard_arrow_down),
focusColor: Theme.of(context).primaryColor,
value: dropdownValue,
onChanged: (newValue) {
setState(() {
dropdownValue = newValue; // THIS HAVE NO IMPACT ON INITAL VALUE
});
},
items: categoriesList,
),
],
),
),
onClosing: () {},
);
}
}
I think if i find a way to acces widget.props from oustide of build method it going to work but I dont know how to do this
You can copy paste run full code below
You can see working demo below
Step 1: Category extends Equatable
import 'package:equatable/equatable.dart';
class Category extends Equatable {
String title;
Category({this.title});
#override
List<Object> get props => [title];
}
Step 2: dropdownValue is Category not String and use initState()
Category dropdownValue;
#override
void initState() {
dropdownValue = widget.categories[0];
super.initState();
}
Step 3: value is category
DropdownMenuItem<Category>(
value: category,
working demo
full code
import 'package:flutter/material.dart';
import 'package:equatable/equatable.dart';
class Category extends Equatable {
String title;
Category({this.title});
#override
List<Object> get props => [title];
}
class TaskSheet extends StatefulWidget {
#override
_TaskSheetState createState() => _TaskSheetState();
final List<Category> categories;
TaskSheet(this.categories);
}
class _TaskSheetState extends State<TaskSheet> {
Category dropdownValue;
#override
void initState() {
dropdownValue = widget.categories[0];
super.initState();
}
#override
Widget build(BuildContext context) {
var categoriesList = widget.categories
.map(
(category) => DropdownMenuItem<Category>(
value: category,
child: Text(category.title),
),
)
.toList();
return BottomSheet(
builder: (context) => Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 16),
child: Column(
children: [
Text('Add new task'),
TextField(
decoration: InputDecoration(labelText: 'What you wanna do?'),
),
DropdownButton<Category>(
icon: Icon(Icons.keyboard_arrow_down),
focusColor: Theme.of(context).primaryColor,
value: dropdownValue,
onChanged: (newValue) {
setState(() {
dropdownValue =
newValue; // THIS HAVE NO IMPACT ON INITAL VALUE
});
print(dropdownValue.title);
},
items: categoriesList,
),
],
),
),
onClosing: () {},
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TaskSheet([
Category(title: "work"),
Category(title: "hobby"),
Category(title: "social")
]),
],
),
),
);
}
}