I am trying to use Flutter Riverpod together with the Date Range Picker.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Riverpod DateRange Picker',
home: HomeScreen(),
);
}
}
class Trip {
final String name;
final DateTimeRange dateTimeRange;
Trip(this.name, this.dateTimeRange);
}
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
Set<Trip> trips = {
Trip('Test 1',
DateTimeRange(start: DateTime(2023, 1, 3), end: DateTime(2023, 1, 6)))
};
return Scaffold(
appBar: AppBar(title: const Text('Riverpod DateRange Picker')),
body: ListView(
children: [
for (final trip in trips)
ListTile(
title: Text(trip.name),
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) =>
TripScreen(trip: trip)));
},
),
],
),
);
}
}
class TripScreen extends ConsumerWidget {
const TripScreen({Key? key, required this.trip}) : super(key: key);
final Trip trip;
@override
Widget build(BuildContext context, WidgetRef ref) {
void _showDateRangePicker() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
locale: const Locale('en', 'GB'),
initialDateRange: trip.dateTimeRange,
saveText: 'Done',
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
);
if (result != null) {
print(result);
}
}
return WillPopScope(
onWillPop: () {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(trip.name),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: () {
_showDateRangePicker();
},
),
Text(
'Start: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.start)}'),
Text(
'End: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.end)}'),
],
))));
}
}
Any help would be much appriciated.
Thanks.
I've created this using Provider but I would like to use Riverpod.
I created "tripsProvider" instance of StateProvider that holds all trip data, like in your case only one value. Home screen watching that provider and displaying data in ListView, when user select item in list I pass index of item and watch that single item on new screen (copy of yours TripScreen). When user update the data of single item I update that list, so update is available on TripScreen and HomeScreen. I also still learning riverpod but hope my answer can help you.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
final tripsProvider = StateProvider<List<Trip>>(
(ref) => [
Trip(
'Test 1',
DateTimeRange(start: DateTime(2023, 1, 3), end: DateTime(2023, 1, 6)),
),
],
);
class Trip {
final String name;
final DateTimeRange dateTimeRange;
const Trip(this.name, this.dateTimeRange);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Riverpod DateRange Picker',
home: HomeScreen(),
);
}
}
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final trips = ref.watch(tripsProvider);
return Scaffold(
appBar: AppBar(title: const Text('Riverpod DateRange Picker')),
body: ListView.builder(
itemCount: trips.length,
itemBuilder: (context, index) {
Trip trip = trips[index];
return ListTile(
title: Text(trip.name),
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => TripScreen(index: index),
),
);
},
);
},
),
);
}
}
class TripScreen extends ConsumerWidget {
int index;
TripScreen({Key? key, required this.index}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final trip = ref.watch(tripsProvider)[index];
void _showDateRangePicker() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
locale: const Locale('en', 'GB'),
initialDateRange: trip.dateTimeRange,
saveText: 'Done',
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
);
if (result != null) {
print(result);
Trip updatedTrip = Trip(trip.name, DateTimeRange(start: result.start, end: result.end));
ref.read(tripsProvider.notifier).update(
(state) {
List<Trip> updatedList = [];
for (int i = 0; i < state.length; i++) {
if (i == index) {
updatedList.add(updatedTrip);
} else {
updatedList.add(state[i]);
}
}
return updatedList;
},
);
}
}
return WillPopScope(
onWillPop: () {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(trip.name),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: () {
_showDateRangePicker();
},
),
Text('Start: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.start)}'),
Text('End: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.end)}'),
],
),
),
),
);
}
}