mirror of
https://github.com/Iconica-Development/flutter_form_wizard.git
synced 2025-05-19 19:03:47 +02:00
Merge branch 'master' into feature/onChange
This commit is contained in:
commit
9e36197a77
12 changed files with 314 additions and 7 deletions
|
@ -1,9 +1,13 @@
|
||||||
## 0.0.1 - September 29th 2022
|
## 0.0.2 - October 10th 2022
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
||||||
## 0.0.2 - October 12th 2022
|
## 0.1.0 - October 12th 2022
|
||||||
|
|
||||||
- Added a multi line plain text input widget
|
- Added a multi line plain text input widget
|
||||||
- Ability to set the scrolldirection of the pageview
|
- Ability to set the scrolldirection of the pageview
|
||||||
- Ability to set the scrollphysics of the pages' scrollview.
|
- Ability to set the scrollphysics of the pages' scrollview.
|
||||||
|
|
||||||
|
## 0.2.0 - October 13th 2022
|
||||||
|
|
||||||
|
- Added date input widget
|
||||||
|
|
|
@ -25,7 +25,7 @@ class _AgePageState extends State<AgePage> {
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
title: "What is your age?",
|
title: "What is your age?",
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
amountOfPages: 3,
|
amountOfPages: 4,
|
||||||
flutterFormWidgets: [
|
flutterFormWidgets: [
|
||||||
FlutterFormInputNumberPicker(
|
FlutterFormInputNumberPicker(
|
||||||
minValue: 12,
|
minValue: 12,
|
||||||
|
|
|
@ -27,7 +27,7 @@ class _CarouselPageState extends State<CarouselPage> {
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
title: "What's your favorite car?",
|
title: "What's your favorite car?",
|
||||||
pageNumber: 3,
|
pageNumber: 3,
|
||||||
amountOfPages: 3,
|
amountOfPages: 4,
|
||||||
flutterFormWidgets: [
|
flutterFormWidgets: [
|
||||||
FlutterFormInputCarousel(
|
FlutterFormInputCarousel(
|
||||||
controller: widget.inputController, items: getCars())
|
controller: widget.inputController, items: getCars())
|
||||||
|
|
44
example/lib/example_pages/date_page.dart
Normal file
44
example/lib/example_pages/date_page.dart
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form/flutter_form.dart';
|
||||||
|
import 'package:form_example/template_page.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
class DatePage extends StatefulWidget {
|
||||||
|
const DatePage({
|
||||||
|
required this.dateController,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final FlutterFormInputPlainTextController dateController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DatePage> createState() => _DatePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DatePageState extends State<DatePage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var size = MediaQuery.of(context).size;
|
||||||
|
var fontSize = size.height / 40;
|
||||||
|
|
||||||
|
return TemplatePage(
|
||||||
|
size: size,
|
||||||
|
fontSize: fontSize,
|
||||||
|
pageNumber: 4,
|
||||||
|
amountOfPages: 4,
|
||||||
|
title: "Please enter a date",
|
||||||
|
flutterFormWidgets: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(40, 0, 40, 40),
|
||||||
|
child: FlutterFormInputDateTime(
|
||||||
|
inputType: FlutterFormDateTimeType.dateTime,
|
||||||
|
dateFormat: DateFormat.yMd(),
|
||||||
|
firstDate: DateTime.now(),
|
||||||
|
label: const Text("Date"),
|
||||||
|
controller: widget.dateController,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ class _NamePageState extends State<NamePage> {
|
||||||
size: size,
|
size: size,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
pageNumber: 2,
|
pageNumber: 2,
|
||||||
amountOfPages: 3,
|
amountOfPages: 4,
|
||||||
title: "Please enter your name",
|
title: "Please enter your name",
|
||||||
flutterFormWidgets: [
|
flutterFormWidgets: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|
|
@ -6,6 +6,8 @@ import 'package:form_example/example_pages/carousel_page.dart';
|
||||||
import 'package:form_example/example_pages/check_page.dart';
|
import 'package:form_example/example_pages/check_page.dart';
|
||||||
import 'package:form_example/example_pages/name_page.dart';
|
import 'package:form_example/example_pages/name_page.dart';
|
||||||
|
|
||||||
|
import 'example_pages/date_page.dart';
|
||||||
|
|
||||||
class FormExample extends ConsumerStatefulWidget {
|
class FormExample extends ConsumerStatefulWidget {
|
||||||
const FormExample({Key? key}) : super(key: key);
|
const FormExample({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -63,6 +65,15 @@ class _FormExampleState extends ConsumerState<FormExample> {
|
||||||
onChanged: (value) => debugPrint(value),
|
onChanged: (value) => debugPrint(value),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
FlutterFormInputPlainTextController dateController =
|
||||||
|
FlutterFormInputPlainTextController(
|
||||||
|
mandatory: true,
|
||||||
|
id: "date",
|
||||||
|
checkPageTitle: (dynamic date) {
|
||||||
|
return "Date: $date";
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -193,6 +204,11 @@ class _FormExampleState extends ConsumerState<FormExample> {
|
||||||
cars: cars,
|
cars: cars,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
FlutterFormPage(
|
||||||
|
child: DatePage(
|
||||||
|
dateController: dateController,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
checkPage: CheckPageExample()
|
checkPage: CheckPageExample()
|
||||||
.showCheckpage(context, size, fontSize, checkPageText),
|
.showCheckpage(context, size, fontSize, checkPageText),
|
||||||
|
|
|
@ -87,7 +87,7 @@ packages:
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
|
|
|
@ -16,6 +16,7 @@ dependencies:
|
||||||
flutter_riverpod: ^1.0.4
|
flutter_riverpod: ^1.0.4
|
||||||
flutter_form:
|
flutter_form:
|
||||||
path: ../
|
path: ../
|
||||||
|
intl: ^0.17.0
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form/utils/translation_service.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import '../../../../../flutter_form.dart';
|
||||||
|
|
||||||
|
/// Generates a [DateTimeInputField] for DateTimes/Dates/Times/DateRanges.
|
||||||
|
/// It requires a [FlutterFormInputController], [inputType], [dateFormat], [firstDate], and [lastDate]
|
||||||
|
class DateTimeInputField extends ConsumerStatefulWidget {
|
||||||
|
const DateTimeInputField({
|
||||||
|
Key? key,
|
||||||
|
required this.inputType,
|
||||||
|
required this.controller,
|
||||||
|
this.label,
|
||||||
|
this.showIcon = true,
|
||||||
|
this.icon = Icons.calendar_today,
|
||||||
|
required this.dateFormat,
|
||||||
|
required this.firstDate,
|
||||||
|
required this.lastDate,
|
||||||
|
}) : super(
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
final FlutterFormDateTimeType inputType;
|
||||||
|
final FlutterFormInputController controller;
|
||||||
|
final DateFormat dateFormat;
|
||||||
|
final bool showIcon;
|
||||||
|
final DateTime? firstDate;
|
||||||
|
final DateTime? lastDate;
|
||||||
|
final IconData icon;
|
||||||
|
final Widget? label;
|
||||||
|
@override
|
||||||
|
ConsumerState<DateTimeInputField> createState() => _DateInputFieldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DateInputFieldState extends ConsumerState<DateTimeInputField> {
|
||||||
|
late final DateTime firstDate;
|
||||||
|
late final DateTime lastDate;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
firstDate = widget.firstDate ??
|
||||||
|
DateTime.now().subtract(
|
||||||
|
const Duration(days: 1000),
|
||||||
|
);
|
||||||
|
lastDate = widget.lastDate ??
|
||||||
|
DateTime.now().add(
|
||||||
|
const Duration(days: 1000),
|
||||||
|
);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String Function(String, {List<String>? params}) _ =
|
||||||
|
getTranslator(context, ref);
|
||||||
|
|
||||||
|
Future<String> getInputFromUser(FlutterFormDateTimeType inputType) async {
|
||||||
|
String userInput = '';
|
||||||
|
switch (inputType) {
|
||||||
|
case FlutterFormDateTimeType.date:
|
||||||
|
DateTime? unformatted = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: firstDate,
|
||||||
|
lastDate: lastDate,
|
||||||
|
);
|
||||||
|
userInput = unformatted != null
|
||||||
|
? widget.dateFormat.format(unformatted)
|
||||||
|
: userInput;
|
||||||
|
break;
|
||||||
|
case FlutterFormDateTimeType.dateTime:
|
||||||
|
await getInputFromUser(FlutterFormDateTimeType.date)
|
||||||
|
.then((value) async {
|
||||||
|
if (value != '') {
|
||||||
|
String secondInput =
|
||||||
|
await getInputFromUser(FlutterFormDateTimeType.time);
|
||||||
|
if (secondInput != '') {
|
||||||
|
userInput = '$value $secondInput';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case FlutterFormDateTimeType.range:
|
||||||
|
userInput = (await showDateRangePicker(
|
||||||
|
context: context,
|
||||||
|
firstDate: firstDate,
|
||||||
|
lastDate: lastDate,
|
||||||
|
).then((value) {
|
||||||
|
return value != null
|
||||||
|
? '${widget.dateFormat.format(value.start)} - ${widget.dateFormat.format(value.end)}'
|
||||||
|
: '';
|
||||||
|
}))
|
||||||
|
.toString();
|
||||||
|
break;
|
||||||
|
case FlutterFormDateTimeType.time:
|
||||||
|
userInput = await showTimePicker(
|
||||||
|
context: context, initialTime: TimeOfDay.now())
|
||||||
|
.then((value) => value == null ? '' : value.format(context));
|
||||||
|
}
|
||||||
|
return userInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextFormField(
|
||||||
|
keyboardType: TextInputType.none,
|
||||||
|
readOnly: true,
|
||||||
|
key: Key(widget.controller.value.toString()),
|
||||||
|
initialValue: widget.controller.value,
|
||||||
|
onSaved: (value) {
|
||||||
|
widget.controller.onSaved(value);
|
||||||
|
},
|
||||||
|
onTap: () async {
|
||||||
|
String userInput = await getInputFromUser(widget.inputType);
|
||||||
|
setState(() {
|
||||||
|
widget.controller.value =
|
||||||
|
userInput != '' ? userInput : widget.controller.value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validator: (value) => widget.controller.onValidate(value, _),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
suffixIcon: widget.showIcon ? Icon(widget.icon) : null,
|
||||||
|
focusColor: Theme.of(context).primaryColor,
|
||||||
|
label: widget.label ?? const Text("Date"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form/src/widgets/input/input_types/input_date_picker/date_picker.dart';
|
||||||
|
import 'package:flutter_form/utils/translation_service.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import '../../../../../flutter_form.dart';
|
||||||
|
|
||||||
|
/// Select Input Types in a [FlutterFormInputDateTime]
|
||||||
|
enum FlutterFormDateTimeType {
|
||||||
|
date,
|
||||||
|
time,
|
||||||
|
dateTime,
|
||||||
|
range,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Input for a dateTime used in a [FlutterForm].
|
||||||
|
///
|
||||||
|
/// Standard controller is [FlutterFormInputDateController].
|
||||||
|
class FlutterFormInputDateTime extends FlutterFormInputWidget {
|
||||||
|
const FlutterFormInputDateTime({
|
||||||
|
Key? key,
|
||||||
|
required FlutterFormInputController controller,
|
||||||
|
Widget? label,
|
||||||
|
this.showIcon = true,
|
||||||
|
required this.inputType,
|
||||||
|
required this.dateFormat,
|
||||||
|
this.firstDate,
|
||||||
|
this.lastDate,
|
||||||
|
this.icon = Icons.calendar_today,
|
||||||
|
}) : super(
|
||||||
|
key: key,
|
||||||
|
controller: controller,
|
||||||
|
label: label,
|
||||||
|
);
|
||||||
|
final bool showIcon;
|
||||||
|
final FlutterFormDateTimeType inputType;
|
||||||
|
final DateFormat dateFormat;
|
||||||
|
final DateTime? firstDate;
|
||||||
|
final DateTime? lastDate;
|
||||||
|
final IconData icon;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
String Function(String, {List<String>? params}) _ =
|
||||||
|
getTranslator(context, ref);
|
||||||
|
super.registerController(context);
|
||||||
|
|
||||||
|
return DateTimeInputField(
|
||||||
|
firstDate: firstDate,
|
||||||
|
lastDate: lastDate,
|
||||||
|
inputType: inputType,
|
||||||
|
controller: controller,
|
||||||
|
dateFormat: dateFormat,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Controller for dates used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
||||||
|
///
|
||||||
|
/// Mainly used by [FlutterFormInputDateTime].
|
||||||
|
class FlutterFormInputDateTimeController
|
||||||
|
implements FlutterFormInputController<String> {
|
||||||
|
FlutterFormInputDateTimeController({
|
||||||
|
required this.id,
|
||||||
|
this.mandatory = true,
|
||||||
|
this.value,
|
||||||
|
this.checkPageTitle,
|
||||||
|
this.checkPageDescription,
|
||||||
|
required this.dateTimeType,
|
||||||
|
required this.dateFormat,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DateFormat dateFormat;
|
||||||
|
final FlutterFormDateTimeType dateTimeType;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool mandatory;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String Function(String? value)? checkPageTitle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String Function(String? value)? checkPageDescription;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void Function(String? value)? onChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSaved(dynamic value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? onValidate(String? value,
|
||||||
|
String Function(String, {List<String>? params}) translator) {
|
||||||
|
if (mandatory) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return translator('shell.form.error.empty');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,3 +5,4 @@ export 'input_password/input_password.dart';
|
||||||
export 'input_plain_text.dart';
|
export 'input_plain_text.dart';
|
||||||
export 'input_slider/input_slider.dart';
|
export 'input_slider/input_slider.dart';
|
||||||
export 'input_switch/input_switch.dart';
|
export 'input_switch/input_switch.dart';
|
||||||
|
export 'input_date_picker/input_date_picker.dart';
|
||||||
|
|
|
@ -6,7 +6,7 @@ homepage:
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.18.0 <3.0.0'
|
sdk: ">=2.18.0 <3.0.0"
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -15,6 +15,7 @@ dependencies:
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_riverpod: ^1.0.4
|
flutter_riverpod: ^1.0.4
|
||||||
|
intl: ^0.17.0
|
||||||
localization: ^2.1.0
|
localization: ^2.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
Loading…
Reference in a new issue