mirror of
https://github.com/Iconica-Development/flutter_form_wizard.git
synced 2025-05-19 10:53:49 +02:00
feat: Add phone field and added some decorations to some fields
This commit is contained in:
parent
09939512f9
commit
929d318668
16 changed files with 246 additions and 113 deletions
|
@ -117,12 +117,15 @@
|
|||
- Updated the `flutter_input_library` from 2.6.0 to 3.0.0
|
||||
|
||||
## 6.2.3 - February 7th 2024
|
||||
|
||||
- Added CI and linter
|
||||
|
||||
## 6.2.4 - February 9th 2024
|
||||
- Updated the `flutter_input_library` from 3.0.0 to 3.0.1
|
||||
|
||||
## 6.2.5 - February 15th 2024
|
||||
|
||||
- Updated the `flutter_input_library` from 3.0.1 to 3.1.0
|
||||
|
||||
## 6.3.0 - February 21th 2024
|
||||
- Updated the `flutter_input_library` from 3.1.0 to 3.2.1
|
||||
- Added `FlutterFormInputPhone` for phone number with dial code selection.
|
||||
- Added `InputDecoration` parameter to the following inputfields: `FlutterFormInputEmail` and `FlutterFormInputPassword`
|
|
@ -26,6 +26,6 @@ subprojects {
|
|||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
|
|
@ -25,6 +25,14 @@ class _FormExampleState extends ConsumerState<FormExample> {
|
|||
|
||||
final String checkPageText = "All entered info: ";
|
||||
|
||||
final phoneInputController = FlutterFormInputPhoneController(
|
||||
id: 'phone',
|
||||
onChanged: (value) {
|
||||
debugPrint(
|
||||
'${value?.dialCode ?? 'no dial'} ${value?.number ?? 'no number'}');
|
||||
},
|
||||
);
|
||||
|
||||
final ageInputController = FlutterFormInputNumberPickerController(
|
||||
id: "age",
|
||||
checkPageTitle: (dynamic amount) {
|
||||
|
@ -177,6 +185,13 @@ class _FormExampleState extends ConsumerState<FormExample> {
|
|||
return Container();
|
||||
},
|
||||
pages: [
|
||||
FlutterFormPage(
|
||||
child: Center(
|
||||
child: FlutterFormInputPhone(
|
||||
controller: phoneInputController,
|
||||
),
|
||||
),
|
||||
),
|
||||
FlutterFormPage(
|
||||
child: AgePage(
|
||||
inputController: ageInputController,
|
||||
|
|
|
@ -68,16 +68,14 @@ packages:
|
|||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "6.2.3"
|
||||
version: "6.2.5"
|
||||
flutter_input_library:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: "3.0.0"
|
||||
resolved-ref: "7024fb7e404fbeae0331bfe8f7c115283d0951ce"
|
||||
url: "https://github.com/Iconica-Development/flutter_input_library"
|
||||
source: git
|
||||
version: "3.0.0"
|
||||
path: "../../flutter_input_library"
|
||||
relative: true
|
||||
source: path
|
||||
version: "3.2.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
|
|
@ -230,99 +230,95 @@ class _FlutterFormState extends State<FlutterForm> {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
PageView(
|
||||
scrollDirection: _formController._options.scrollDirection,
|
||||
controller: _formController.getPageController(),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
for (int i = 0; i < widget.options.pages.length; i++) ...[
|
||||
Form(
|
||||
key: _formController.getKeys()[i],
|
||||
child: fs.FormState(
|
||||
formController: _formController.getFormPageControllers()[i],
|
||||
child: CustomScrollView(
|
||||
physics: _formController._options.scrollPhysics ??
|
||||
const ClampingScrollPhysics(),
|
||||
slivers: [
|
||||
SliverFillRemaining(
|
||||
hasScrollBody: false,
|
||||
child: widget.options.pages[i].child,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
if (widget.options.checkPage != null)
|
||||
Column(
|
||||
children: [
|
||||
if (widget.options.checkPage!.title != null)
|
||||
widget.options.checkPage!.title!,
|
||||
Expanded(
|
||||
Widget build(BuildContext context) => Stack(
|
||||
children: [
|
||||
PageView(
|
||||
scrollDirection: _formController._options.scrollDirection,
|
||||
controller: _formController.getPageController(),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
for (int i = 0; i < widget.options.pages.length; i++) ...[
|
||||
Form(
|
||||
key: _formController.getKeys()[i],
|
||||
child: fs.FormState(
|
||||
formController: _formController.getFormPageControllers()[i],
|
||||
child: CustomScrollView(
|
||||
physics: _formController._options.scrollPhysics ??
|
||||
const ClampingScrollPhysics(),
|
||||
slivers: [
|
||||
SliverFillRemaining(
|
||||
hasScrollBody: false,
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
widget.options.checkPage!.mainAxisAlignment,
|
||||
children: getResultWidgets(),
|
||||
),
|
||||
child: widget.options.pages[i].child,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.options.nextButton != null)
|
||||
widget.options.nextButton!(
|
||||
_formController.getCurrentStep(),
|
||||
_formController.getCheckpages(),
|
||||
)
|
||||
else
|
||||
Align(
|
||||
alignment: AlignmentDirectional.bottomCenter,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 40,
|
||||
vertical: 15,
|
||||
),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
],
|
||||
if (widget.options.checkPage != null)
|
||||
Column(
|
||||
children: [
|
||||
if (widget.options.checkPage!.title != null)
|
||||
widget.options.checkPage!.title!,
|
||||
Expanded(
|
||||
child: CustomScrollView(
|
||||
physics: _formController._options.scrollPhysics ??
|
||||
const ClampingScrollPhysics(),
|
||||
slivers: [
|
||||
SliverFillRemaining(
|
||||
hasScrollBody: false,
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
widget.options.checkPage!.mainAxisAlignment,
|
||||
children: getResultWidgets(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.options.nextButton != null)
|
||||
widget.options.nextButton!(
|
||||
_formController.getCurrentStep(),
|
||||
_formController.getCheckpages(),
|
||||
)
|
||||
else
|
||||
Align(
|
||||
alignment: AlignmentDirectional.bottomCenter,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 40,
|
||||
vertical: 15,
|
||||
),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
await _formController.autoNextStep();
|
||||
},
|
||||
child: Text(
|
||||
_formController.getCurrentStep() >=
|
||||
widget.options.pages.length - 1
|
||||
? 'Finish'
|
||||
: 'Next',
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
await _formController.autoNextStep();
|
||||
},
|
||||
child: Text(
|
||||
_formController.getCurrentStep() >=
|
||||
widget.options.pages.length - 1
|
||||
? 'Finish'
|
||||
: 'Next',
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.options.backButton != null)
|
||||
widget.options.backButton!(
|
||||
_formController.getCurrentStep(),
|
||||
_formController.getCheckpages(),
|
||||
widget.options.pages.length,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (widget.options.backButton != null)
|
||||
widget.options.backButton!(
|
||||
_formController.getCurrentStep(),
|
||||
_formController.getCheckpages(),
|
||||
widget.options.pages.length,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
List<Widget> getResultWidgets() {
|
||||
var widgets = <Widget>[];
|
||||
|
|
|
@ -27,13 +27,13 @@ class FlutterFormInputCarousel extends FlutterFormInputWidget<int> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
return input.FlutterFormInputCarousel(
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
onChanged: controller.onChanged,
|
||||
initialValue: controller.value ?? 0,
|
||||
items: items,
|
||||
|
|
|
@ -41,7 +41,7 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
super.registerController(context);
|
||||
|
||||
return input.FlutterFormInputDateTime(
|
||||
|
@ -55,7 +55,7 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
|||
inputType: inputType,
|
||||
onChanged: (value) => controller.onChanged?.call(value),
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
initialValue: controller.value,
|
||||
dateFormat: dateFormat,
|
||||
initialDate: initialDate,
|
||||
|
|
|
@ -16,13 +16,16 @@ class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
|
|||
super.focusNode,
|
||||
super.label,
|
||||
bool? enabled,
|
||||
this.decoration,
|
||||
}) : super(
|
||||
enabled: enabled ?? true,
|
||||
);
|
||||
|
||||
final InputDecoration? decoration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
|
@ -33,12 +36,9 @@ class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
|
|||
controller.onSaved(value);
|
||||
},
|
||||
focusNode: focusNode,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
onChanged: (value) => controller.onChanged?.call(value),
|
||||
decoration: InputDecoration(
|
||||
focusColor: Theme.of(context).primaryColor,
|
||||
label: label ?? const Text('Email'),
|
||||
),
|
||||
decoration: decoration,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class FlutterFormInputNumberPicker extends FlutterFormInputWidget<int> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
|
@ -34,7 +34,7 @@ class FlutterFormInputNumberPicker extends FlutterFormInputWidget<int> {
|
|||
minValue: minValue,
|
||||
maxValue: maxValue,
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
onChanged: (value) => controller.onChanged?.call(value),
|
||||
initialValue: controller.value ?? minValue,
|
||||
);
|
||||
|
|
|
@ -16,24 +16,28 @@ class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
|
|||
super.focusNode,
|
||||
super.label,
|
||||
bool? enabled,
|
||||
this.decoration,
|
||||
}) : super(
|
||||
enabled: enabled ?? true,
|
||||
);
|
||||
|
||||
final InputDecoration? decoration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.registerController(context);
|
||||
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
return input.FlutterFormInputPassword(
|
||||
enabled: enabled,
|
||||
initialValue: controller.value,
|
||||
focusNode: focusNode,
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
onChanged: (value) => controller.onChanged?.call(value),
|
||||
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
||||
decoration: decoration,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
113
lib/src/widgets/input/input_types/input_phone.dart
Normal file
113
lib/src/widgets/input/input_types/input_phone.dart
Normal file
|
@ -0,0 +1,113 @@
|
|||
// SPDX-FileCopyrightText: 2022 Iconica
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// ignore_for_file: overridden_fields
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||
|
||||
/// Input for plain text input used in a [FlutterForm].
|
||||
///
|
||||
/// Standard controller is [FlutterFormInputPlainTextController].
|
||||
class FlutterFormInputPhone extends FlutterFormInputWidget<input.PhoneNumber?> {
|
||||
const FlutterFormInputPhone({
|
||||
required super.controller,
|
||||
super.key,
|
||||
super.focusNode,
|
||||
super.label,
|
||||
this.decoration,
|
||||
this.enabled = true,
|
||||
this.numberFieldStyle,
|
||||
this.dialCodeSelectorStyle,
|
||||
this.dialCodeSelectorPadding = const EdgeInsets.only(top: 6),
|
||||
this.textAlignVertical = TextAlignVertical.top,
|
||||
});
|
||||
|
||||
final InputDecoration? decoration;
|
||||
@override
|
||||
final bool enabled;
|
||||
final TextStyle? numberFieldStyle;
|
||||
final TextStyle? dialCodeSelectorStyle;
|
||||
final EdgeInsets dialCodeSelectorPadding;
|
||||
final TextAlignVertical textAlignVertical;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
var inputDecoration = decoration ??
|
||||
InputDecoration(
|
||||
label: label ?? const Text('Phone field'),
|
||||
);
|
||||
|
||||
return input.FlutterFormInputPhone(
|
||||
numberFieldStyle: numberFieldStyle,
|
||||
dialCodeSelectorStyle: dialCodeSelectorStyle,
|
||||
enabled: enabled,
|
||||
initialValue: controller.value,
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
onChanged: (value) => controller.onChanged?.call(value),
|
||||
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
||||
decoration: inputDecoration,
|
||||
dialCodeSelectorPadding: dialCodeSelectorPadding,
|
||||
textAlignVertical: textAlignVertical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FlutterFormInputPhoneController
|
||||
implements FlutterFormInputController<input.PhoneNumber?> {
|
||||
FlutterFormInputPhoneController({
|
||||
required this.id,
|
||||
this.mandatory = true,
|
||||
this.value,
|
||||
this.checkPageTitle,
|
||||
this.checkPageDescription,
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
String? id;
|
||||
|
||||
@override
|
||||
input.PhoneNumber? value;
|
||||
|
||||
@override
|
||||
bool mandatory;
|
||||
|
||||
@override
|
||||
String Function(input.PhoneNumber? value)? checkPageTitle;
|
||||
|
||||
@override
|
||||
String Function(input.PhoneNumber? value)? checkPageDescription;
|
||||
|
||||
@override
|
||||
void Function(input.PhoneNumber? value)? onChanged;
|
||||
|
||||
@override
|
||||
void Function(input.PhoneNumber? value)? onSubmit;
|
||||
|
||||
@override
|
||||
void onSaved(input.PhoneNumber? value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@override
|
||||
String? onValidate(
|
||||
input.PhoneNumber? value,
|
||||
String Function(String, {List<String>? params}) translator,
|
||||
) {
|
||||
if (mandatory) {
|
||||
if (value == null || value.number == null) {
|
||||
return translator('Field can not be empty');
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -43,7 +43,7 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
|
@ -59,7 +59,7 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
|||
initialValue: controller.value,
|
||||
focusNode: focusNode,
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
onChanged: (value) => controller.onChanged?.call(value),
|
||||
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
||||
decoration: inputDecoration,
|
||||
|
@ -103,7 +103,7 @@ class FlutterFormInputMultiLine extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
return input.FlutterFormInputMultiLine(
|
||||
enabled: enabled,
|
||||
|
@ -114,7 +114,7 @@ class FlutterFormInputMultiLine extends StatelessWidget {
|
|||
maxCharacters: maxCharacters,
|
||||
onChanged: controller.onChanged,
|
||||
onSaved: controller.onSaved,
|
||||
validator: (v) => controller.onValidate(v, _),
|
||||
validator: (v) => controller.onValidate(v, translator),
|
||||
textCapitalization: textCapitalization,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ class FlutterFormInputSlider extends FlutterFormInputWidget<double> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
return input.FlutterFormInputSlider(
|
||||
focusNode: focusNode,
|
||||
onSaved: controller.onSaved,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _ = getTranslator(context);
|
||||
var translator = getTranslator(context);
|
||||
|
||||
super.registerController(context);
|
||||
|
||||
|
@ -29,7 +29,7 @@ class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
|
|||
focusNode: focusNode,
|
||||
onSaved: controller.onSaved,
|
||||
onChanged: controller.onChanged,
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
validator: (value) => controller.onValidate(value, translator),
|
||||
initialValue: controller.value ?? false,
|
||||
widgetType: input.BoolWidgetType.switchWidget,
|
||||
);
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
export 'package:flutter_input_library/flutter_input_library.dart'
|
||||
show PhoneNumber;
|
||||
|
||||
export 'input_carousel/input_carousel.dart';
|
||||
export 'input_date_picker/input_date_picker.dart';
|
||||
export 'input_email.dart';
|
||||
export 'input_number_picker/input_number_picker.dart';
|
||||
export 'input_password/input_password.dart';
|
||||
export 'input_phone.dart';
|
||||
export 'input_plain_text.dart';
|
||||
export 'input_slider/input_slider.dart';
|
||||
export 'input_switch/input_switch.dart';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_form_wizard
|
||||
description: A new Flutter package project.
|
||||
version: 6.2.5
|
||||
version: 6.3.0
|
||||
homepage: https://github.com/Iconica-Development/flutter_form_wizard
|
||||
|
||||
publish_to: none
|
||||
|
@ -18,7 +18,7 @@ dependencies:
|
|||
flutter_input_library:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_input_library
|
||||
ref: 3.1.0
|
||||
ref: 3.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in a new issue