How to set initial value from cache to dropdown button?
have submitted button, if click submits button should add to drop-down button value. Now it's working. I need to add initial value to the drop-down button. and If add initial value and when click to submit button without selecting a value in dropdown selecting value should ant to pass
Container(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<WorkSource>(
isExpanded: true,
value: _workSources,
items: workSources.map((WorkSource value) {
return DropdownMenuItem<WorkSource>(
value: value,
child: Text(
value.description,
overflow: TextOverflow.ellipsis,
),
);
}).toList(),
onChanged: (value) => setState(() {
workSourceIndex = value.id;
_workSources = value;
}),
style: Theme.of(context).textTheme.title,
_workSources in your code should be the initial value. Just assign value to that in initState().
Related
Is it possible to make the secondary property of the SwitchListTile tapable? In this case, an icon is used:
SwitchListTile(
title: const Text('Lights'),
value: _lights,
onChanged: (bool value) { setState(() { _lights = value; }); },
secondary: const Icon(Icons.lightbulb_outline), //can this be selected?
)
Ideally, instead of creating another widget, I would like to use the Icon in the secondary property to display a message when the user selects it.
Currently when the icon, or entire widget is selected, the switch is toggled. What is the best way to handle this action?
Thanks.
Wrap your Icon inside InkWell to handle the tap :
secondary: InkWell(
onTap: () {
print("click light");
},
child: const Icon(Icons.lightbulb_outline),
),
More info here: https://docs.flutter.io/flutter/material/InkWell-class.html
You could wrap your Icon in an IconButton.
SwitchListTile(
title: const Text('Lights'),
value: _lights,
onChanged: (value) => setState(() => _lights = value),
secondary: IconButton(
icon: Icon(Icons.lightbulb_outline),
onPressed: () {},
),
)
As soon as a TextField gets focused, an object which stores if it's enabled changes so that the TextField gets disabled immediately. This also happens when another TextField above gets focused.
The TextField is placed inside a StatefulWidget and a Category object contains another object called Goal which contains a bool variable if it's enabled or disabled. This variable is also used to enable or disable the TextField.
TextField(
controller: _goalAmountController,
enabled: widget.category.goal.enabled,
decoration: InputDecoration(
labelText: "Goal Amount",
border: OutlineInputBorder(),
),
onChanged: (value) {
try {
widget.category.goal.amount = double.parse(value);
} on Exception {
//TODO display error message
print("Invalid Goal-Amount");
}
},
),
There's also a switch below the TextField to enable or disable the Goal by setting it's enabled variable.
SwitchListTile(
value: widget.category.goal.enabled,
title: Text("Enable Goal"),
onChanged: (value) {
setState(
() {
widget.category.goal.enabled = value;
},
);
},
),
I found out that it seems as if the click on a TextField would replace the Goal object with a new one which has false as the default value for enabled.
Try to use FocusNodes instead :
FocusNode textNode = FocusNode();
TextField(
focusNode: textNode,
controller: _goalAmountController,
enabled: widget.category.goal.enabled,
decoration: InputDecoration(
labelText: "Goal Amount",
border: OutlineInputBorder(),
),
later when you want to disable this textField when the user interact with another widget you can call:
textNode.unfocus() ;
The full page code is very long but my DropdownButton widget code like this.
The problems are,
first: I can't update my selectedCity, it doesn't get an update. Also, the print function calls null, since my cityList data is like [new york, paris, london] etc...
second: flutter doesn't change focus from any TextField to DropdownButton fully. I mean, clicked TextField, then DropdownButton but focus reverts to that TextField after the button click. It is default action of Flutter?
List<dynamic> _cityList;
String _selectedCity;
#override
Widget build(BuildContext context) {
return DropdownButton(
value: _selectedCity,
style: TextStyle(
fontSize: 11,
color: textColor,
),
items: _cityList.map((city) {
return DropdownMenuItem<String>(
child: Padding(
padding: const EdgeInsets.only(left: 4),
child: Text(city),
),
);
}).toList(),
onChanged: (String value) {
setState(() {
_selectedCity = value;
print(_selectedCity);
});
},
isExpanded: true,
);
}
Edit: The solution of resetting FocusNode after selecting an item from DropdownMenuItem is adding this line inside of setstate like this:
this: FocusScope.of(context).requestFocus(new FocusNode());
to here: onChanged:(){setSate((){here}}
I hope it will help you. I have modified your code a little bit
List<dynamic> _cityList;
String _selectedCity;
It will show the Dropdown Button and when you click on it and select any value showing in the print
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
body: ListView(
children: [
Column(
children: <Widget>[
DropdownButton<String>(
items: _cityList.map((dynamic value) {
return DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedCity = value;
print(_selectedCity);
});
},
),
],
),
],
),
);
}
for the focus problem you should use focusNodes one with the drop down list and another with the text field https://docs.flutter.io/flutter/widgets/FocusNode-class.html.
I am using flutter to make a simple application.
In the below code, when TextBox changed event is fired then I call the method named updateTitle().
But I have to call the same method updateTitle(), when key is up, as we use in javascript and other languages too.
TextField(
controller: titleController,
style: textStyle,
onChanged: (value) => updateTitle(),
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
)),
),
For your use case, the onChangedworks just like onkyeup would work. Everytime that the user tap a new character in the textfield, it is fired.
In order to enable/disable a button you should listen to this event, do the test to see if the field isn't empty, modify a variable that will handle the button state, and call setState().
This is just a sample code. Not tested, but should work as is.
class _SoAnswerState extends State<SoAnswer> {
bool _buttonActive = false;
#override
Widget build(BuildContext context) {
...
TextField(
controller: titleController,
style: textStyle,
onChanged: (value) => updateButtonState(value), // onChanged return the value of the field
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
)
),
),
...
}
void updateButtonState(String text){
// if text field has a value and button is inactive
if(text != null && text.length > 0 && !_buttonActive){
setState(() {
_buttonActive = true;
}
}else if((text == null || text.length == 0) && _buttonActive){
setState(() {
_buttonActive = false;
}
}
}
Edit: add more information about the events
In JavaScript, the onkeyup event handler fires when the user releases a key that was previously pressed. When the user press and release a key inside a text field, the text field value changes. The onChanged listener in Flutter fires when the text field value changes. When working with a typing interface, where the user uses a tradicional keyboard, it is not a good idea to listen to all the changes of a text field, because the user can press and hold a key, leading the application to repeat the onchanged event too many times, once for every character repetition. That's not the case with a mobile interface, where the user (usually) can't press and hold a key.
when i try to add two dropDownFormField in a row its showing an exception i don't know why they are not fitting into a row. i tried to wrap it also not working.when add two dropDown buttons in a row it works perfectly.but i want use validator so i am using dropdownformfield
Widget collgDD= Wrap(children:<Widget>[Row(
children:<Widget>[DropdownButtonFormField(
value: selectedcollg,
items: collg.map((value){
return new DropdownMenuItem<String>(child: Text(value),
value: value,);
}).toList(),
hint: Text("select ur collg"),
onChanged: (value){
setState(() {
selectedcollg=value;
});
},
),
DropdownButtonFormField(
value: selectbranch,
items: branch.map((value){
return new DropdownMenuItem<String>(child: Text(value),
value: value,);
}).toList(),
hint: Text("select ur collg"),
onChanged: (value){
setState(() {
selectbranch=value;
});
},
)
])]);
Use flexible widget
Widget collgDD = Row(children: <Widget>[
Flexible(
child: dropdown1
),
Flexible(
child: dropdown2,
)
]);