Skip to content

Instantly share code, notes, and snippets.

@zgunz42
Last active March 12, 2019 12:24
Show Gist options
  • Save zgunz42/649bb829b561826a5e83203628a3df4b to your computer and use it in GitHub Desktop.
Save zgunz42/649bb829b561826a5e83203628a3df4b to your computer and use it in GitHub Desktop.
Show datepicker when field clicked using RxDart way - https://www.facebook.com/groups/1738284952897937/2173932705999824
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rxdart/rxdart.dart';
class RiwayatKunjunganBloc {
final riwayatKunjunganAPI = RiwayatKunjunganAPI();
final _dateQuery = BehaviorSubject<DateTime>();
Observable<List<RiwayatKunjunganModel>> _results;
Function get dateQueryAdd => _dateQuery.sink.add;
Observable<DateTime> get dateQueryStream => _dateQuery.stream;
Observable<List<RiwayatKunjunganModel>> get result => _results;
RiwayatKunjunganBloc() {
_results = dateQueryStream
.debounce(Duration(milliseconds: 500))
.distinct()
.asyncMap((riwayatKunjunganAPI.fetchDataKunjungan));
}
dispose() {
_dateQuery.close();
}
}
class RiwayatKunjunganModel {
final String prefix;
final DateTime date;
RiwayatKunjunganModel(this.prefix, this.date);
String get message => (prefix + ': ${date.month} month');
@override
String toString() {
// TODO: implement toString
return '$prefix: $date';
}
}
// fake remote API
class RiwayatKunjunganAPI {
Future<List<RiwayatKunjunganModel>> fetchDataKunjungan(date) async =>
[RiwayatKunjunganModel('date', date)];
}
class Vm extends StatefulWidget {
@override
VmState createState() {
return new VmState();
}
}
class VmState extends State<Vm> {
final TextEditingController _monthController = TextEditingController();
RiwayatKunjunganBloc riwayatKunjunganBloc;
DateTime selectedDate;
@override
void initState() {
super.initState();
riwayatKunjunganBloc = RiwayatKunjunganBloc();
riwayatKunjunganBloc.result.listen((results) {
setState(() {
final model = results.firstWhere((dm) => dm.date == selectedDate, orElse: () => results.first);
_monthController.text = model.message;
});
});
}
@override
Widget build(BuildContext context) {
return Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: InkWell(
onTap: () {
showDatePicker(
context: context,
initialDate: selectedDate ?? DateTime.now(),
lastDate: DateTime(2020),
firstDate: DateTime(2011))
.then(riwayatKunjunganBloc.dateQueryAdd);
},
child: TextField(
controller: _monthController,
enabled: false, // disable show keyboard for now, wait for better solution
decoration: InputDecoration(
hintText: 'Pilih Bulan',
labelText: 'Bulan kunjungan',
hasFloatingPlaceholder: true),
),
),
),
);
}
@override
void dispose() {
riwayatKunjunganBloc.dispose();
super.dispose();
}
}
void main() {
testWidgets('bloc datetime picker update the value of field', (tester) async {
await tester.pumpWidget(MaterialApp(
home: Vm(),
));
final Finder field = find.byType(InkWell).first;
final today = DateTime.now();
await tester.tap(field);
await tester.pumpAndSettle(const Duration(seconds: 2));
final Finder previousMonthIcon = find.byWidgetPredicate((Widget w) =>
w is IconButton && (w.tooltip?.startsWith('Previous month') ?? false));
await tester.tap(previousMonthIcon.first);
await tester.pumpAndSettle(const Duration(seconds: 1));
await tester.tap(find.text('OK'));
// Wait for debounce stream duration is more than on stream
await tester.pumpAndSettle(Duration(seconds: 1));
final Finder editableTextFinder =
find.widgetWithText(TextField, 'date: ${today.month - 1} month');
expect(editableTextFinder, findsOneWidget);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment