Flutter, pass datetime value to a method
You are using form in your class but it is not useful at all in this case. I recommend you to remove the form, then you replace the onSaved by onChanged like that :
onChanged: (value) {
setState(() {
dateRange = value!;
});
Create a method to send your searched value :
void _sendSearch(String value) {
_debounce.run(() {
setState(() {
searchedValue = value;
});
});
}
You can now replace your onChanged method for the namespace :
onChanged: _sendSearch
And finally replace your extanded method by this one ( now you give to your deploymentList the dateRangeand the searchedValue:
Expanded(child: DeploymentList(searchedValue, dateRange: dateRange))
So each time you change the daterange or the searched value, the component will be rebuilt.
Kévin
Updated on December 29, 2022Comments
-
Kévin over 1 year
I currently have a page where i can select a date range, after that i have a search bar, and then a listview. When i select dates, and i click on submit, dates are displayed. Now i need to pass those dates to a method, but it is received as null. It seems that i forget something to be able to use this variable..
class HistoriquePage extends StatefulWidget { final String title; final String namespace; const HistoriquePage({Key? key, required this.title, required this.namespace}) : super(key: key); @override _HistoriquePageState createState() => _HistoriquePageState(); } class _HistoriquePageState extends State<HistoriquePage> { GlobalKey<FormState> myFormKey = new GlobalKey(); DateTimeRange? dateRange; Post? user; void _submitForm() { final FormState? form = myFormKey.currentState; form!.save(); } @override Widget build(BuildContext context) => Scaffold( appBar: AppBar( title: Text(widget.title), ), body: SafeArea( child: Form( key: myFormKey, child: Column( children: [ Container( child: SafeArea( child: DateRangeField( enabled: true, initialValue: DateTimeRange( start: DateTime.parse("2020-01-01"), end: DateTime.now()), firstDate: new DateTime(2020), decoration: InputDecoration( labelText: 'Interval de temps pour la recherche', prefixIcon: Icon(Icons.date_range), border: OutlineInputBorder(), ), onSaved: (value) { setState(() { dateRange = value!; }); }), ), ), Container( padding: EdgeInsets.all(16), child: TextField( decoration: InputDecoration( prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), labelText: 'Select the namespace...', ), onChanged: (searchedValue) { setState(() { HistoriqueService.filterList(searchedValue, dateRange: dateRange); }); }), ), ElevatedButton( child: Text('Submit'), onPressed: _submitForm, ), if (dateRange != null) Text("Saved value is: ${dateRange.toString()}"), Expanded(child: DeploymentList()) ], ), ), ), ); } class HistoriqueService { static Future<List<User>> filterList(String value, {DateTimeRange? dateRange}) async { print("value" + value); if (dateRange != null) { print("dateRange: " + dateRange.toString()); } List<User> postsList = await HttpService.fetchHistorique(); return postsList .where((user) => user.name.toLowerCase().contains(value.toLowerCase())) .toList(); } }
-
SilkeNL almost 3 yearsIf I understand correctly you can do
historiqueService.yourFunction(dateRange)
in this case thehistoriqueService
is made withfinal HistoriqueService historiqueService = HistoriqueService()
-
Kévin almost 3 years@SilkeNL This is already what i have here ; HistoriqueService.filterList(searchedValue, dateRange: dateRange);
-
SilkeNL almost 3 yearsAre you sure it set the state right? Can you print dateRange in
onChanged: (searchedValue) { setState(() { HistoriqueService.filterList(searchedValue, dateRange: dateRange); }); }),
-
Kévin almost 3 yearsThe state for the dataRange is above here :
onSaved: (value) {setState(() { dateRange = value!;});
As i said, i can see the value when i click on Submit -
SilkeNL almost 3 yearsI understand but something isn't right in the code. To find out where, try printing dateRange in multiple places. Where is it a date and where is it null?
-
Kévin almost 3 yearsText("Saved value is: ${dateRange.toString()}") is working, after i press the Submit button. It is null in the filterList method.
-
Abel Rodríguez almost 3 yearsThe
filterList
function returns aFuture
. Put theasync
modifier to theonChanged
function and theawait
keyword when you call thefilterList
function, like this:onChanged: (searchedValue) async { setState(() { await HistoriqueService.filterList(searchedValue, dateRange: dateRange); });}
. Hope this works! -
Kévin almost 3 years@AbelRodríguez Hum no it breaks :
( [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: setState() callback argument returned a Future. E/flutter (27540): The setState() method on _HistoriquePageState#7bf88 was called with a closure or method that returned a Future. Maybe it is marked as "async". E/flutter (27540): Instead of performing asynchronous work inside a call to setState(), first execute the work (without updating the widget state), and then synchronously update the state inside a call to setState().
daterange is not printed -
SilkeNL almost 3 yearsThe error states the problem and possible solution:
Instead of performing asynchronous work inside a call to setState(), first execute the work (without updating the widget state), and then synchronously update the state inside a call to setState().
So maybe get the value for inside the setState first, then set the state for real? -
Abel Rodríguez almost 3 yearsJust put the
filterList
function outside thesetState
, like this:onChanged: (searchedValue) async { await HistoriqueService.filterList(searchedValue, dateRange: dateRange); setState(() {});}
. I already tested it and it works like a charm.
-