in flutter I can not change value from dropdown button - flutter

below the StatefulWidget class Customdropdownbutton where I defined the dropdown button
class Customdropdownbutton extends StatefulWidget {
Customdropdownbutton({#required this.defaultValue, #required this.listValue, this.enable});
String defaultValue;
List<String> listValue;
bool enable;
#override
_CustomdropdownbuttonState createState() => _CustomdropdownbuttonState();
}
class _CustomdropdownbuttonState extends State<Customdropdownbutton> {
#override
Widget build(BuildContext context) {
String _valore;
return DropdownButton<String>(
value: widget.defaultValue.isEmpty ? widget.listValue[0] : _valore,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: widget.enable ? (String newValue) {
setState(() {
_valore = newValue;
});
} : null,
items: widget.listValue.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
below I try to instantiate the class Customdropdownbutton and in UI I see the dropdown button but I can not change the value (the text selected is alwais the widget.listValue[0])
class MyMain extends StatefulWidget {
#override
Widget build(BuildContext context) {
final auth = Provider.of<AuthBase>(context, listen: false);
final String emailMy = auth.currentUser.email;
return scaffold(
.....
body: _buildFormChildren(emailMy),
}
List<Widget> _buildFormChildren(String emailMy) {
List<String> listValue = ['1a', '2b'];
String defaultValue = '1a';
bool enable = true;
return [
**Customdropdownbutton(defaultValue: '', listValue : listValue, enable: true, ),**
],
....
}
}

In the build method of your _CustomdropdownbuttonState, you check if widget.defaultValue is empty (which always is since you're not changing it) and it evaluates widget.listValue[0]. Even if you change _valore, the condition will keep checking if widget.defaultValue is empty. You can do the following:
class _CustomdropdownbuttonState extends State<Customdropdownbutton> {
// Use _valore as a property instead of a local variable
String _valore;
#override
void initState() {
super.initState();
// Use _valore to store the default value
_valore = widget.defaultValue;
}
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
// Check _valore instead of widget.defaultValue
value: _valore.isEmpty ? widget.listValue[0] : _valore,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: widget.enable ? (String newValue) {
setState(() {
_valore = newValue;
});
} : null,
items: widget.listValue.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}

Related

How can I only check one checkbox at time?

How can I select/check only one checkbox to be checked at time?
And below is my code
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Checkbox(
checkColor: Colors.white,
value: isChecked,
onChanged: (bool value) {
setState(() {
isChecked = value;
// ignore: unnecessary_statements
passData(certId);
});
},
),
],
)),
Option1 - Using a map to maintain the state
Create a map:
final Map<int, bool> _state = {};
then, check if the value for that index is true/false:
return ListView.builder(itemBuilder: (context, index) {
return CheckboxListTile(
value: _state[index] ?? false,
onChanged: (value) {
setState(() {
_state[index] = value!;
});
},
title: Text(_data[index].text),
);
});
Option 2 - using a model:
class CheckBoxModel {
bool isChecked = false;
String text = "";
CheckBoxModel({required this.isChecked, required this.text});
}
and then, generate a List of 30 widgets:
final _data = List.generate(
30, (index) => CheckBoxModel(isChecked: false, text: "Item $index"));
Now, use a ListView.builder and based on the index, to update the corresponding value:
class Testing extends StatefulWidget {
const Testing({Key? key}) : super(key: key);
#override
State<Testing> createState() => _TestingState();
}
class _TestingState extends State<Testing> {
#override
Widget build(BuildContext context) {
return ListView.builder(itemBuilder: (context, index) {
return CheckboxListTile(
value: _data[index].isChecked,
onChanged: (value) {
setState(() {
_data[index].isChecked = value!;
});
},
title: Text(_data[index].text),
);
});
}
}
See also
Expansion tile trailing icon updates all in list on interaction with one tile. How can I only change the icon for the expanded tile?

How to avoid the user can to write on DropdownMenu in flutter?

I need to avoid the user can to type on the DropdownMenu Widget, but I cannot find how to do that. I was looking for in the api.flutter.dev, But I did not find anything.I would appreciate the help.
class TDSMDropdown extends StatefulWidget {
final List<String> items;
final String? value;
final String? hintText;
final String? label;
final void Function(String?)? onSelected;
final TextEditingController? controller;
const TDSMDropdown({
Key? key,
required this.items,
this.value,
this.hintText,
required this.label,
this.onSelected,
this.controller,
}) : super(key: key);
#override
State<TDSMDropdown> createState() => _TDSMDropdownState();
}
class _TDSMDropdownState extends State<TDSMDropdown> {
// final TextEditingController colorController = TextEditingController();
String? selectedValue;
#override
void initState() {
super.initState();
selectedValue = widget.value;
}
_handleOnSelected(String? newVal) {
widget.onSelected!(newVal);
}
#override
Widget build(BuildContext context) {
return DropdownMenu<String>(
width: MediaQuery.of(context).size.width,
enableSearch: false,
// controller: colorController,
label: widget.label == null ? null : Text(widget.label!),
dropdownMenuEntries: widget.items
.map((e) => DropdownMenuEntry<String>(value: e, label: e))
.toList(),
// inputDecorationTheme: _decoration(),
onSelected: widget.onSelected != null ? _handleOnSelected : null,
);
}
Information
Flutter version 3.7.0
Material 3
dart 2.19.0
Attached the image of the current behavior. Currently I can write on the dropdown input, I do not want that.
I need the same behavior that the DropdownButton2 package has.
you can use DropdownButtonFormField widget for this here is the example
DropdownButtonFormField<int>(
decoration: const InputDecoration(
label: Text("Role"),
),
value: 0,
items: [
const DropdownMenuItem(
alignment: Alignment.center,
value: 0,
enabled: false,
child: Text("Select Your role"),
),
DropdownMenuItem(
value: 1,
child: const Text("Admin"),
onTap: () {
role = "Admin";
},
),
DropdownMenuItem(
value: 2,
child: const Text("Miner"),
onTap: () {
role = "Miner";
},
),
DropdownMenuItem(
value: 3,
child: const Text("Polisher"),
onTap: () {
role = "Polisher";
},
),
DropdownMenuItem(
value: 4,
child: const Text("Certifier"),
onTap: () {
role = "Certifier";
},
),
DropdownMenuItem(
value: 5,
child: const Text("Q/A"),
onTap: () {
role = "Q/A";
},
),
],
onChanged: (value) {
value = value;
},
),
which will give you this result

Why is the value of the drop-down list (button) not assigned?

I have about 7 DropDownButton, so I created a class in which I just change the values. Here is my class -
class DropDown extends StatelessWidget {
late List<DropdownMenuItem<dynamic>> menuItem;
String? menuValue;
String? hintValue;
DropDown(this.menuItem, this.menuValue, this.hintValue);
#override
Widget build(BuildContext context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter mystate){
return Container(
child: DropdownButton(
underline: Container(
height: 0.1,
color: Colors.transparent,
),
hint: Text('$hintValue'),
value: menuValue,
icon: const Icon(Icons.keyboard_arrow_down),
items: menuItem,
onChanged: (dynamic newValue) {
mystate(() {
menuValue = newValue!;
});
}
)
)
);
}) ;
}
}
Below is how I display these dropdowns -
DropDown(LoginClass.typeModemsDropDown, LoginClass.typeModemsValue, 'Выберите тип модема'),
const SizedBox(
height: 12,
),
DropDown(LoginClass.vendorCountersDropDown, LoginClass.vendorCountersValue, 'text'),
When you try to display in the console LoginClass.vendorCountersValue - the value of null. However, if at this point, I will output print(menuValue); -
mystate(() {
menuValue = newValue!;
print(menuValue);
});
Then, it displays the correct values ​​in the console for me
data - Here is how I am getting the data -
LoginClass.viewModemsDropDown .add(DropdownMenuItem<dynamic>(value: resp['data'][i]['id'].toString(), child: Text(resp['data'][i]['attributes'] ['view_name']))),
// LoginClass.viewModemsDropDown - ["blue": 1, "red": 2] !VALUE!
Tell me, how can I see the values of the selected item anywhere in the code?
Can you point out my mistake and tell me what I'm doing wrong?
You can use a callback method on your DropDown. Also use named constructor cases like this.
class DropDown extends StatelessWidget {
final Function(dynamic) callback;
final List<DropdownMenuItem<dynamic>> menuItem;
final String? menuValue;
final String? hintValue;
const DropDown({
Key? key,
required this.callback,
required this.menuItem,
required this.menuValue,
required this.hintValue,
}) : super(key: key);
#override
Widget build(BuildContext context) {
String? currentValue = menuValue;
return StatefulBuilder(
builder: (BuildContext context, StateSetter mystate) {
return Container(
child: DropdownButton(
underline: Container(
height: 0.1,
color: Colors.transparent,
),
hint: Text('$hintValue'),
value: menuValue,
icon: const Icon(Icons.keyboard_arrow_down),
items: menuItem,
onChanged: (dynamic newValue) {
mystate(() {
currentValue = newValue!;
});
callback(currentValue);
},
),
);
});
}
}
And use case
DropDown(
menuItem: ["a", "b"]
.map(
(e) => DropdownMenuItem(
child: Text(e),
value: e,
),
)
.toList(),
callback: (p0) {
print(p0);
},
hintValue: "Set",
menuValue: "a",
),

RadioListTile is not working with setstate

What is working when i click on radio button it is not changing
class OnBoardingCheckBoxWithActionWidget extends StatefulWidget {
String label;
Function onClick;
OnBoardingCheckBoxWithActionWidget(this.label, {this.onClick});
#override
_OnBoardingCheckBoxWithActionWidgetState createState() =>
_OnBoardingCheckBoxWithActionWidgetState();
}
class _OnBoardingCheckBoxWithActionWidgetState
extends State<OnBoardingCheckBoxWithActionWidget> {
bool checked = true;
#override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RadioListTile(
value: checked,
groupValue: checked,
toggleable: true,
title: Text("${widget.label}"),
onChanged: (val) {
if (widget.onClick != null) {
widget.onClick(val);
}
setState(() {
print("$checked");
checked = !checked;
print("$checked");
});
},
),
),
); // Card(child: Row(children: [Expanded(child: RadioListTile())],),);
}
}
You're trying to change some value from your Parent Stateful widget.
Try changing your current widget like
class OnBoardingCheckBoxWithActionWidget
extends StatelessWidget {
String label;
Function onClick;
var groupValue;
var buttonValue;
OnBoardingCheckBoxWithActionWidget(this.label, {this.onClick, this.groupValue,, this.buttonValue});
#override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RadioListTile(
value: buttonValue,
groupValue: groupValue,
toggleable: true,
title: Text("${this.label}"),
onChanged: (val) {
if (this.onClick != null) {
this.onClick(val);
}
},
),
),
); // Card(child: Row(children: [Expanded(child: RadioListTile())],),);
}
}
And then call it like
OnBoardingCheckBoxWithActionWidget("Button1", onClick: (value){
setState((){
///Your Other Code
if(value){
groupValue = 'button1';
}
});
},
groupValue: someGroupValueVariableInState, buttonValue: 'button1')
Note that, the groupValue and buttonValue variables will always be some other variables other than booleans. When groupValue == buttonValue, the corresponding button will automatically marked as checked.

Is it possible in a dropdown button the displayed value to not be in the menu?

I tried to do it but I get an error. I was wondering if there is some kind of loophole.
Also, is there a way for the menu to open below the displayed value?
Here is the code:
import 'package:flutter/material.dart';
import './grile_view.dart';
class Grile extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return GrileState();
}
}
class GrileState extends State<Grile> {
var _bGrile = ['bgrila 1', 'bgrila 2'];
var _bio = 'bgrila 1';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: ListView(
children: <Widget>[
// DropdownButton
DropdownButton<String>(
items: _bGrile.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem)
);
}).toList(),
onChanged: (value){
Navigator.push(context, MaterialPageRoute(builder: (context) =>
GView()));
},
value: _bio
),
// DropdownButton End
]
)
)
);
} // build
} // GrileState
I am new at programming so excuse anything dumb I wrote in the code.
The DropdownButton class contains a very handy hint property. According to the DropdownButton documentation:
If [value] is null and [hint] is non-null, the [hint] widget is
displayed as a placeholder for the dropdown button's value.
What does this mean for you?
All you have to do is add a hint widget to your DropdownButton and then remove the assignment from your dynamic value.
Here's a brief example of a DropdownButton with a hint property:
class DropDownPage extends StatefulWidget {
#override
_DropDownPageState createState() => _DropDownPageState();
}
class _DropDownPageState extends State<DropDownPage> {
int dropdownValue; // Notice how this isn't assigned a value.
#override
Widget build(BuildContext context) {
return Center(
child: DropdownButton(
// Here's the hint property. I used a Text widget,
// but you can use any widget you like
hint: Text("Pick a Widget"),
value: dropdownValue,
items: [
DropdownMenuItem(child: Text("FlatButton"), value: 0),
DropdownMenuItem(child: Text("Container"), value: 1),
DropdownMenuItem(child: Text("Scaffold"), value: 2),
DropdownMenuItem(child: Text("GestureDetector"), value: 3),
],
onChanged: (value) {
setState(() {
dropdownValue = value;
});
},
));
}
}
This is the result:
So in your code, here's what you have to do in your own code.
Edit this: var _bio = 'bgrila 1';
And change it to this: var _bio;
Then add a hint property to your DropdownButton:
DropdownButton<String>(
hint: Text("Pick a *****"), // Replace with your hint widget
items: _bGrile.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem)
);
}).toList(),
onChanged: (value){
Navigator.push(context, MaterialPageRoute(builder: (context) =>
GView()));
},
value: _bio
),
So that your entire code looks like this:
class Grile extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return GrileState();
}
}
class GrileState extends State<Grile> {
var _bGrile = ['bgrila 1', 'bgrila 2'];
var _bio;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: ListView(
children: <Widget>[
// DropdownButton
DropdownButton<String>(
hint: Text("Pick a *******"),
items: _bGrile.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem)
);
}).toList(),
onChanged: (value){
Navigator.push(context, MaterialPageRoute(builder: (context) =>
GView()));
},
value: _bio
),
// DropdownButton End
]
)
)
);
} // build
} // GrileState