When I change the chosen item in dropdownMenuItem, my dialog doesn't change it to what I selected.
I have a dropdown that shows what the client can select, when I select one of them the selected item doesn't display in the field, the hint keeps there.
it starts with "SERVIÇO:" and keeps like that after changing the item. the variable gets the value but it doesn't change in display.
Future<void> _addObraServico(BuildContext context) async {
return showDialog(
context: context,
child: new Dialog(
backgroundColor: blueSoftwar,
child: new Column(children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Text(
"SERVIÇOS",
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: new Theme(
data: Theme.of(context).copyWith(
canvasColor: orangeSoftwar,
),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(
5.0) // <--- border radius here
),
),
child: DropdownButton<String>(
isExpanded: true,
value: obraServicoDropDown,
icon: const Icon(
Icons.arrow_downward,
color: Colors.white,
),
style: const TextStyle(color: Colors.white),
underline: SizedBox(),
onChanged: (String newValue) {
setState(() {
obraServicoDropDown = newValue;
print(obraServicoDropDown);
});
},
items: <String>['', 'SERVICO1', 'SERVICO2', 'SERVICO3']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
);
}).toList(),
hint: Container(
child: Text(
" SERVIÇO:",
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.end,
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: new TextField(
style: TextStyle(color: Colors.white, fontSize: 20),
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
borderSide: BorderSide(color: Colors.white),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
borderSide: BorderSide(color: Colors.white),
),
hintText: "Descrição *",
hintStyle: TextStyle(fontSize: 20.0, color: Colors.white),
),
controller: _tDescricaoObra,
),
),
if (showAlert)
Text(
"Preencha os campos",
style: TextStyle(fontSize: 20, color: Colors.red),
),
new FlatButton(
color: Colors.orange,
child: new Text(
"CADASTRAR",
style: TextStyle(color: Colors.white),
),
onPressed: () {
if (obraServicoDropDown == null || _tDescricaoObra.text.isEmpty) {
showAlert = true;
} else {
ServicoObra servico = new ServicoObra();
servico.servico = obraServicoDropDown;
servico.descricao = _tDescricaoObra.text;
setState(() {
servicos.add(servico);
});
obraServicoDropDown = null;
_tDescricaoObra.clear();
showAlert = false;
Navigator.pop(context);
}
},
),
]),
),
);
}
Calling setState from showDialog changes the state of the widget, but it does not rebuild the dialog, because Flutter does not consider the state of the dialog to be changed just because we changed the state of the widget that called the dialog.
The way to fix this is to make the dialog stateful; either through StatefulBuilder or as a StatefulWidget. In either case, now changing the dropdown state in the dialog will only change it in the dialog; so we also need a callback from the main widget to change the state there as well. Demo snippet below.
class DialogDropdown extends StatefulWidget {
const DialogDropdown({Key? key}) : super(key: key);
@override
State<DialogDropdown> createState() => _DialogDropdownState();
}
class _DialogDropdownState extends State<DialogDropdown> {
String? _grade;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text("Dialog Dropdown"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_grade ?? "Unknown",
style: Theme.of(context).textTheme.headline4,
),
const Text(
'Grade',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => gradeDialog(),
);
},
tooltip: 'Change Grade',
child: const Icon(Icons.arrow_upward),
),
);
}
void _changeGrade(_newGrade) {
setState(
() {
_grade = _newGrade;
},
);
}
StatefulBuilder gradeDialog() {
return StatefulBuilder(
builder: (context, _setter) {
return Dialog(
child: Padding(
padding: const EdgeInsets.all(15),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(_grade ?? "Unknown"),
const SizedBox(height: 30),
DropdownButton<String>(
value: _grade,
onChanged: (String? _newGrade) {
_setter(
() {
_grade = _newGrade!;
},
);
_changeGrade(_newGrade);
},
items: ["A", "B"].map<DropdownMenuItem<String>>(
(String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
},
).toList(),
),
],
),
),
);
},
);
}
}