I have previously posted about this problem I am still facing Which is to return data from a Stateful widget back to a Stateless Widget
The Widget I am using is Dat
For more time saving solution for returning value from another widget and using it, here's an example for Flutter Dropdown:
import 'package:flutter/material.dart';
import 'package:paxi_ride/constant.dart';
class BuildDropdown extends StatefulWidget {
final ValueChanged<String> onChanged;
String defaultValue, selectedValue, dropdownHint;
List<String> itemsList;
BuildDropdown(
{Key key,
this.itemsList,
this.defaultValue,
this.dropdownHint,
this.onChanged})
: super(key: key);
@override
_BuildDropdownState createState() => _BuildDropdownState();
}
class _BuildDropdownState extends State<BuildDropdown> {
String _value;
@override
Widget build(BuildContext context) {
return Container(
// height: 40,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 0),
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
color: Colors.white,
child: DropdownButton<String>(
items: widget.itemsList.map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
},
).toList(),
value: _value == null ? widget.defaultValue : _value,
isExpanded: true,
onChanged: (String value) {
setState(() {
_value = value;
});
widget.onChanged(value);
},
hint: Text(widget.dropdownHint),
style: TextStyle(
fontSize: 14,
color: brownColorApp,
),
iconEnabledColor: brownColorApp,
iconSize: 14,
underline: Container(),
),
);
}
}
Call this widget from another widget where you want to get selected value like this:
String selectedValue; //class field
BuildDropdown(
itemsList: ['Option 1','Option 2'],
defaultValue: 'Option 1',
dropdownHint: 'Select Required Option',
onChanged: (value) {
selectedValue = value;
},
),
Use this value wherever needed, it will be changed as dropdown selection is changed.
In this situation passing data with Navigator is not suitable. Because there isn't page transition between the page and your dateTime
Widget. I recommend you to implement ValueChanged
callback to pass data between widgets in same screen.
It's little bit tricky. But material.dart
's widgets often use this technique. I hope this will help you!
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DateTime dateT;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add a Reminder'),
),
body: new Container(
padding: new EdgeInsets.all(20.0),
child: new Form(
child: new ListView(
children: <Widget>[
new TextFormField(
keyboardType: TextInputType.text,
// Use email input type for emails.
decoration: new InputDecoration(
hintText: 'Title of reminder',
),
),
dateTime(
onDateTimeChanged: (newDateTime) {
dateT = newDateTime;
},
),
RaisedButton(
child: Text('Save'),
onPressed: () {
Navigator.pop(context);
},
)
],
),
),
),
);
}
}
class dateTime extends StatefulWidget {
final ValueChanged<DateTime> onDateTimeChanged;
dateTime({Key key, this.onDateTimeChanged}) : super(key: key);
@override
dateTimeState createState() => dateTimeState();
}
class dateTimeState extends State<dateTime> {
DateTime dateT;
InputType inputType = InputType.both;
final formats = {
InputType.both: DateFormat("EEEE, MMMM d, yyyy 'at' h:mma"),
InputType.date: DateFormat('yyyy-MM-dd'),
InputType.time: DateFormat("HH:mm"),
};
Widget build(BuildContext context) => Container(
child: DateTimePickerFormField(
inputType: InputType.both,
editable: true,
format: formats[inputType],
decoration: InputDecoration(
labelText: 'Date/Time', hasFloatingPlaceholder: false),
onChanged: (dt) {
widget.onDateTimeChanged(dt);
},
),
);
}
(Btw your dateAndTimeWidget
is a method, is not a Widget. So if you assign it to Column`s children(List), Flutter framework cannot understand.)