Compare commits

..

24 commits

Author SHA1 Message Date
Freek van de Ven
6d4db87ff1 feat: add onBack callback for the FlutterFormOptions 2024-09-05 13:09:17 +02:00
Freek van de Ven
5528664fb7 chore: add component release workflow 2024-09-03 14:21:33 +02:00
5eb914c23a chore: ready the package for deployment to the pub server 2024-09-03 14:21:33 +02:00
9af9822fc1 chore: add fvm configuration to gitignore 2024-09-03 14:21:33 +02:00
Gorter-dev
204d0c6ca2
Merge pull request #50 from Iconica-Development/feature/multiple_choice
feat: add multiple choice form field
2024-07-01 16:45:35 +02:00
mike doornenbal
a79b0c3ad3 feat: add multiple choice form field 2024-07-01 16:43:36 +02:00
Gorter-dev
18ac2dd82f
Merge pull request #49 from Iconica-Development/feature/dropdownfield
feat: add dropdownfield
2024-07-01 08:54:54 +02:00
mike doornenbal
a88defd186 feat: add dropdownfield 2024-06-28 14:22:33 +02:00
Gorter-dev
a9d3a2c751
Merge pull request #48 from Iconica-Development/chore/upgrade-intl
chore(deps): loosen dep on intl
2024-05-14 14:20:37 +02:00
Bart Ribbers
335a1e1dd1 chore: upgrade version to 6.3.2 2024-05-14 14:19:08 +02:00
Bart Ribbers
ae071cef41 chore(deps): loosen dep on intl
The latest Flutter requires intl 0.19.0 and now every app/package
depending on us fails to build with the latest Flutter because we were
explicitly requiring 0.18.0

Minor upgrades should be safe anyway, we only care for major versions
upgrade, so loosen the requirements a bit to support anything from
0.18.0 up to (but not including) 1.0.0
2024-05-14 14:17:26 +02:00
Freek van de Ven
48534c0db1
Merge pull request #47 from Iconica-Development/refactor/replace-ShellTranslationService
refactor: replace shelltranslationservice with validationMessage input
2024-02-29 16:52:11 +01:00
Vick Top
7bed6b06b7 doc: update pubspec and changelog 2024-02-29 16:50:16 +01:00
Vick Top
c2fac70838 refactor: expose FlutterFormInputDateTime params from flutter_input_library 2024-02-29 16:11:48 +01:00
Vick Top
b1ca468085 refactor: replace shelltranslationservice with validationMessage input 2024-02-29 15:43:10 +01:00
Freek van de Ven
1b9844c5d0
Merge pull request #43 from Iconica-Development/doc/improve-documentation
doc: create documentation for files
2024-02-29 13:25:56 +01:00
Freek van de Ven
f526dc0830
Merge pull request #44 from Iconica-Development/feature/phone_input_field
feat: Add phone field and added some decorations to some fields
2024-02-21 16:13:55 +01:00
Jacques
929d318668 feat: Add phone field and added some decorations to some fields 2024-02-21 16:02:31 +01:00
Vick Top
7b3a34064c doc: create documentation for files 2024-02-20 13:28:59 +01:00
Freek van de Ven
09939512f9
Merge pull request #42 from Iconica-Development/6.2.5
6.2.5
2024-02-15 09:54:55 +01:00
mike doornenbal
08d9c3c67c 6.2.5 2024-02-15 09:53:32 +01:00
Freek van de Ven
9a55bbb410
Merge pull request #41 from Iconica-Development/update-component-documentation-workflow-correct
Add component-documentation.yml correct
2024-02-13 16:35:04 +01:00
Vick Top
b51a4fec21 fix(ci): run dart format 2024-02-13 15:51:39 +01:00
Vick Top
42333adfc1 feat(documentation): Create component-documentation.yml workflow file 2024-02-13 13:35:54 +01:00
34 changed files with 996 additions and 401 deletions

View file

@ -0,0 +1,14 @@
name: Iconica Standard Component Documentation Workflow
# Workflow Caller version: 1.0.0
on:
release:
types: [published]
workflow_dispatch:
jobs:
call-iconica-component-documentation-workflow:
uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master
secrets: inherit
permissions: write-all

14
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,14 @@
name: Iconica Standard Component Release Workflow
# Workflow Caller version: 1.0.0
on:
release:
types: [published]
workflow_dispatch:
jobs:
call-global-iconica-workflow:
uses: Iconica-Development/.github/.github/workflows/component-release.yml@master
secrets: inherit
permissions: write-all

4
.gitignore vendored
View file

@ -29,3 +29,7 @@ migrate_working_dir/
.packages
build/
.metadata
# FVM Version Cache
.fvm/
.fvmrc

View file

@ -1,124 +1,129 @@
## 0.0.2 - October 10th 2022
## 6.6.0 - September 5th 2024
- Added `onBack` callback to the `FlutterFormOptions` to detect when the back button is pressed
- Initial release
## 6.5.0 - July 1st 2024
- Added `FlutterFormMultipleChoice` for multiple choice selection
## 0.1.0 - October 12th 2022
## 6.4.0 - June 28th 2024
- Added `FlutterFormInputDropdown` for dropdown selection
- Added style property to `FlutterFormInputEmail`
- Added a multi line plain text input widget
- Ability to set the scrolldirection of the pageview
- Ability to set the scrollphysics of the pages' scrollview.
## 6.3.2 - May 15th 2024
- Loosened the dependency on intl to be more compatible with several Flutter versions
## 0.2.0 - October 13th 2022
## 6.3.1 - February 29th 2024
- Removed `TranslationService` and add `validationMessage` property to fields with validation.
- Added a way to override a input field validator.
- Exposed all properties for `FlutterFormInputDateTime` provided by `flutter_input_library`.
- Added date input widget
## 6.3.0 - February 21st 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 input fields: `FlutterFormInputEmail` and `FlutterFormInputPassword`
## 1.0.0 - October 13th 2022
## 6.2.5 - February 15th 2024
- Updated the `flutter_input_library` from 3.0.1 to 3.1.0
- Fix: Proper use of generics
- Inputcontrollers now have an onChange.
- Added switch input field
## 6.2.4 - February 9th 2024
- Updated the `flutter_input_library` from 3.0.0 to 3.0.1
## 1.0.1 - October 13th 2022
## 6.2.3 - February 7th 2024
- Added CI and linter
- Added forgotten onChanged parameter on date input field
## 6.2.2 - February 6th 2024
- Updated the `flutter_input_library` from 2.6.0 to 3.0.0
## 1.0.2 - October 13th 2022
## 6.2.1 - January 12th 2024
- Pass on the `initialValue` property to FlutterFormMultiLine
- Added forgotten icon parameter on date input field and scrollpadding on text inputfield
## 2.0.0 - October 26th 2022
- Added the id of the input field on the input check widget.
- Ability to set the height of the carousel input field.
- InputController now contains the onSubmit callback.
## 2.0.1 - October 27th 2022
- onChange of switch input not firing fixed
## 4.0.2 - November 29th 2022
- Name change to flutter_form_wizard
## 4.0.3 - November 29th 2022
- Change from input to `flutter_input_library`
## 5.0.0 - November 29th 2022
- `flutter_input_library` now enforces 24h time requirements
## 5.0.4 - January 12th 2023
- Add FocusNode option to inputs
## 5.0.5 - January 12th 2023
- Expose translations
## 5.0.6 - January 12th 2023
- `flutter_input_library` datetime validator fix
## 5.0.7 - January 12th 2023
- `flutter_input_library` add styling text datetime fix
## 5.0.8 - January 18th 2023
- `flutter_input_library` add focusNode option to `FlutterFormInputMultiLine`
## 5.0.9 - January 18th 2023
- `flutter_input_library` add initial time picker parameter
## 6.0.0 - march 28th 2023
- Bump `flutter_input_library` to version 2.0.0
- Remove unnecessary `riverpod` dependency
## 6.1.0 - May 12th 2023
- Make compatible to flutter 3.10
## 6.1.1 - August 10th 2023
- Bump `flutter_input_library` to version 2.2.0
## 6.1.2 - August 11th 2023
- Bump `flutter_input_library` to version 2.2.1
## 6.1.3 - September 26th 2023
- Fix date format for datecontroller
## 6.1.4 - October 26th 2023
- Bump `flutter_input_library` to version 2.3.0
## 6.1.5 - October 26th 2023
- Bump `flutter_input_library` to version 2.4.0
## 6.1.6 - October 26th 2023
- Add enabled property to FlutterFormInputPlainText and FlutterFormInputDateTime
## 6.1.7 - November 1st 2023
- pass on the show icon property to flutter form input date time widget
## 6.2.0 - December 14th 2023
- Pass on the `textCapitalization` property to FlutterFormPlainText and FlutterFormMultiLine
## 6.1.8 - December 6th 2023
- Pass on the style property to the FlutterFormPlainText input widget
- Bump `flutter_input_library` to version 2.5.0
## 6.2.0 - December 14th 2023
- Pass on the `textCapitalization` property to FlutterFormPlainText and FlutterFormMultiLine
## 6.1.7 - November 1st 2023
- Pass on the show icon property to flutter form input date time widget
## 6.2.1 - January 12th 2024
- Pass on the `initialValue` property to FlutterFormMultiLine
## 6.1.6 - October 26th 2023
- Add enabled property to FlutterFormInputPlainText and FlutterFormInputDateTime
## 6.2.2 - February 6th 2024
- Updated the `flutter_input_library` from 2.6.0 to 3.0.0
## 6.1.5 - October 26th 2023
- Bump `flutter_input_library` to version 2.4.0
## 6.2.3 - February 7th 2024
## 6.1.4 - October 26th 2023
- Bump `flutter_input_library` to version 2.3.0
- Added CI and linter
## 6.1.3 - September 26th 2023
- Fix date format for date controller
## 6.2.4 - February 9th 2024
- Updated the `flutter_input_library` from 3.0.0 to 3.0.1
## 6.1.2 - August 11th 2023
- Bump `flutter_input_library` to version 2.2.1
## 6.1.1 - August 10th 2023
- Bump `flutter_input_library` to version 2.2.0
## 6.1.0 - May 12th 2023
- Make compatible with Flutter 3.10
## 6.0.0 - March 28th 2023
- Bump `flutter_input_library` to version 2.0.0
- Remove unnecessary `riverpod` dependency
## 5.0.9 - January 18th 2023
- `flutter_input_library` add initial time picker parameter
## 5.0.8 - January 18th 2023
- `flutter_input_library` add focusNode option to `FlutterFormInputMultiLine`
## 5.0.7 - January 12th 2023
- `flutter_input_library` add styling text datetime fix
## 5.0.6 - January 12th 2023
- `flutter_input_library` datetime validator fix
## 5.0.5 - January 12th 2023
- Expose translations
## 5.0.4 - January 12th 2023
- Add FocusNode option to inputs
## 5.0.0 - November 29th 2022
- `flutter_input_library` now enforces 24h time requirements
## 4.0.3 - November 29th 2022
- Change from input to `flutter_input_library`
## 4.0.2 - November 29th 2022
- Name change to flutter_form_wizard
## 2.0.1 - October 27th 2022
- onChange of switch input not firing fixed
## 2.0.0 - October 26th 2022
- Added the id of the input field on the input check widget.
- Ability to set the height of the carousel input field.
- InputController now contains the onSubmit callback.
## 1.0.2 - October 13th 2022
- Added forgotten icon parameter on date input field and scroll padding on text input field
## 1.0.1 - October 13th 2022
- Added forgotten onChanged parameter on date input field
## 1.0.0 - October 13th 2022
- Fix: Proper use of generics
- Input controllers now have an onChange.
- Added switch input field
## 0.2.0 - October 13th 2022
- Added date input widget
## 0.1.0 - October 12th 2022
- Added a multi-line plain text input widget
- Ability to set the scroll direction of the page view
- Ability to set the scroll physics of the pages' scroll view.
## 0.0.2 - October 10th 2022
- Initial release

View file

@ -1,45 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: android
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: ios
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: linux
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: macos
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: web
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: windows
create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View file

@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View file

@ -35,6 +35,7 @@ class _AgePageState extends State<AgePage> {
minValue: 12,
maxValue: 120,
controller: widget.inputController,
validationMessage: 'Please fill in your age.',
),
],
);

View file

@ -34,7 +34,10 @@ class _CarouselPageState extends State<CarouselPage> {
amountOfPages: 4,
flutterFormWidgets: [
FlutterFormInputCarousel(
controller: widget.inputController, items: getCars())
controller: widget.inputController,
items: getCars(),
validationMessage: 'Validation error message.',
)
],
);
}

View file

@ -46,6 +46,7 @@ class _DatePageState extends State<DatePage> {
),
label: const Text("Custom date label"),
controller: widget.dateController,
validationMessage: 'Please fill in a date.',
),
),
],

View file

@ -40,6 +40,7 @@ class _NamePageState extends State<NamePage> {
child: FlutterFormInputPlainText(
label: const Text("First Name"),
controller: widget.firstNameController,
validationMessage: 'Please fill in your first name.',
),
),
if (widget.showLastName)
@ -48,6 +49,7 @@ class _NamePageState extends State<NamePage> {
child: FlutterFormInputPlainText(
label: const Text("Last Name"),
controller: widget.lastNameController,
validationMessage: 'Please fill in your last name.',
),
),
],

View file

@ -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,14 @@ class _FormExampleState extends ConsumerState<FormExample> {
return Container();
},
pages: [
FlutterFormPage(
child: Center(
child: FlutterFormInputPhone(
controller: phoneInputController,
validationMessage: 'Please fill in a valid phone number',
),
),
),
FlutterFormPage(
child: AgePage(
inputController: ageInputController,

View file

@ -45,10 +45,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.5"
version: "1.0.8"
fake_async:
dependency: transitive
description:
@ -68,24 +68,24 @@ packages:
path: ".."
relative: true
source: path
version: "6.2.3"
version: "6.5.0"
flutter_input_library:
dependency: transitive
description:
path: "."
ref: "3.0.0"
resolved-ref: "7024fb7e404fbeae0331bfe8f7c115283d0951ce"
ref: "3.4.0"
resolved-ref: cdc06bbb7933ba7ac2835e29d2c8fabf69e5f5a6
url: "https://github.com/Iconica-Development/flutter_input_library"
source: git
version: "3.0.0"
version: "3.4.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "2.0.3"
flutter_localizations:
dependency: transitive
description: flutter
@ -95,10 +95,10 @@ packages:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: "371f6e8acb69dbe8aa3e0a50c8a65f8a9352b599134d585cc4923261cb5ae4d6"
sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.5.1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -108,58 +108,82 @@ packages:
dependency: "direct main"
description:
name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.18.1"
version: "0.19.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: "5cfd6509652ff5e7fe149b6df4859e687fca9048437857cb2e65c8d780f396e3"
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
version: "2.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
version: "0.12.16"
version: "0.12.16+1"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.5.0"
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.10.0"
version: "1.15.0"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
version: "1.9.0"
riverpod:
dependency: transitive
description:
name: riverpod
sha256: "899cd0999b2f3b798349d9b5639cfea81d406c011bd914097145ff92e91b29f9"
sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.5.1"
sky_engine:
dependency: transitive
description: flutter
@ -185,10 +209,10 @@ packages:
dependency: transitive
description:
name: state_notifier
sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
url: "https://pub.dev"
source: hosted
version: "0.7.2+1"
version: "1.0.0"
stream_channel:
dependency: transitive
description:
@ -217,10 +241,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.2"
vector_math:
dependency: transitive
description:
@ -229,14 +253,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
web:
vm_service:
dependency: transitive
description:
name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
version: "14.2.5"
sdks:
dart: ">=3.2.0-194.0.dev <4.0.0"
flutter: ">=3.0.0"
dart: ">=3.3.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

View file

@ -16,7 +16,7 @@ dependencies:
flutter_riverpod: ^2.1.1
flutter_form_wizard:
path: ../
intl: ^0.18.0
intl: any
dev_dependencies:
flutter_test:

View file

@ -9,4 +9,3 @@ export 'src/form.dart';
export 'src/widgets/input/abstractions.dart';
export 'src/widgets/input/input_types/input_types.dart';
export 'utils/form.dart';
export 'utils/translation_service.dart';

View file

@ -230,10 +230,7 @@ class _FlutterFormState extends State<FlutterForm> {
}
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
return Stack(
Widget build(BuildContext context) => Stack(
children: [
PageView(
scrollDirection: _formController._options.scrollDirection,
@ -322,7 +319,6 @@ class _FlutterFormState extends State<FlutterForm> {
),
],
);
}
List<Widget> getResultWidgets() {
var widgets = <Widget>[];
@ -491,7 +487,7 @@ class FlutterFormController extends ChangeNotifier {
Future<void> previousStep() async {
_currentStep -= 1;
_options.onBack?.call(_currentStep);
_checkingPages = false;
notifyListeners();

View file

@ -4,20 +4,26 @@
import 'package:flutter_form_wizard/flutter_form.dart';
/// Controller class for managing input controllers in a Flutter form.
class FlutterFormPageController {
/// List of input controllers.
List<FlutterFormInputController> _controllers = [];
/// Registers an input controller.
void register(FlutterFormInputController inputController) {
_controllers.add(inputController);
}
/// Clears all registered input controllers.
void clearControllers() {
_controllers = [];
}
/// Checks if an input controller is registered with a given ID.
bool _isRegisteredById(String id) =>
_controllers.any((element) => element.id == id);
/// Retrieves the input controller associated with the provided ID.
FlutterFormInputController? getController(String key) {
if (_isRegisteredById(key)) {
return _controllers.firstWhere((element) => element.id == key);
@ -25,6 +31,7 @@ class FlutterFormPageController {
return null;
}
/// Retrieves all values from registered input controllers.
Map<String, dynamic> getAllValues() {
var values = <String, dynamic>{};

View file

@ -5,15 +5,19 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_wizard/src/utils/form_page_controller.dart';
/// Widget for managing form state and providing access to form controller.
class FormState extends InheritedWidget {
/// Constructor for FormState.
const FormState({
required super.child,
required this.formController,
super.key,
});
/// The form controller associated with this FormState.
final FlutterFormPageController formController;
/// Retrieves the nearest ancestor FormState from the given context.
static FormState of(BuildContext context) {
var result = context.dependOnInheritedWidgetOfExactType<FormState>();
assert(result != null, 'No FormStat found in context');

View file

@ -122,6 +122,6 @@ abstract class FlutterFormInputController<T> {
/// [onValidate] is used to validate the given input by the user.
String? onValidate(
T? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
);
}

View file

@ -16,24 +16,27 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
class FlutterFormInputCarousel extends FlutterFormInputWidget<int> {
const FlutterFormInputCarousel({
required super.controller,
required this.validationMessage,
required this.items,
super.key,
super.label,
this.validator,
this.height = 425,
});
final List<Widget> items;
final double height;
final String validationMessage;
final String? Function(int?)? validator;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
return input.FlutterFormInputCarousel(
onSaved: controller.onSaved,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
onChanged: controller.onChanged,
initialValue: controller.value ?? 0,
items: items,
@ -86,7 +89,7 @@ class FlutterFormInputCarouselController
@override
String? onValidate(
int? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {}

View file

@ -13,40 +13,77 @@ import 'package:intl/intl.dart';
///
/// Standard controller is [FlutterFormInputDateController].
class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
/// Creates a [FlutterFormInputDateTime].
///
/// The [controller], [inputType], [dateFormat] are required parameters.
/// The [label] parameter specifies the label of the input field.
/// The [showIcon] parameter determines whether to show an icon
/// with the input field.
/// The [firstDate] and [lastDate] parameters specify the range
/// of selectable dates.
/// The [initialDate] parameter specifies the initial date for
/// the input field.
/// The [initialDateTimeRange] parameter specifies the initial
/// date time range for the input field.
/// The [icon] parameter specifies the icon to show with the input field.
/// The [enabled] parameter specifies whether the input field is enabled.
/// The [onTapEnabled] parameter specifies whether tapping on
/// the input field is enabled.
const FlutterFormInputDateTime({
required super.controller,
required this.inputType,
required this.dateFormat,
required this.validationMessage,
this.decoration,
this.style,
super.key,
super.label,
this.label,
this.showIcon = true,
this.firstDate,
this.lastDate,
this.initialDate,
this.initialDateTimeRange,
this.initialTime,
this.icon = Icons.calendar_today,
this.initialValue,
this.onChanged,
this.onSaved,
this.validator,
this.autovalidateMode = AutovalidateMode.disabled,
this.timePickerEntryMode = TimePickerEntryMode.dial,
this.enabled = true,
this.onTapEnabled = true,
});
final TextStyle? style;
final InputDecoration? decoration;
final Widget? label;
final bool showIcon;
final input.FlutterFormDateTimeType inputType;
final DateFormat dateFormat;
final DateTime? initialDate;
final DateTimeRange? initialDateTimeRange;
final TimeOfDay? initialTime;
final DateTime? firstDate;
final DateTime? lastDate;
final IconData icon;
final String? initialValue;
final String? Function(String?)? validator;
final String validationMessage;
final void Function(String?)? onSaved;
final void Function(String?)? onChanged;
final AutovalidateMode autovalidateMode;
final TimePickerEntryMode timePickerEntryMode;
final bool enabled;
final bool onTapEnabled;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
return input.FlutterFormInputDateTime(
enabled: enabled,
showIcon: showIcon,
decoration: decoration,
onTapEnabled: onTapEnabled,
label: label,
icon: icon,
@ -55,7 +92,8 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
inputType: inputType,
onChanged: (value) => controller.onChanged?.call(value),
onSaved: controller.onSaved,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
initialValue: controller.value,
dateFormat: dateFormat,
initialDate: initialDate,
@ -70,6 +108,12 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
/// Mainly used by [FlutterFormInputDateTime].
class FlutterFormInputDateTimeController
implements FlutterFormInputController<String> {
/// Creates a [FlutterFormInputDateTimeController].
///
/// The [id], [dateTimeType], and [dateFormat] are required parameters.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [initialDate], [initialDateTimeRange], [checkPageTitle],
/// [checkPageDescription], and [onChanged] parameters are optional.
FlutterFormInputDateTimeController({
required this.id,
required this.dateTimeType,
@ -121,11 +165,11 @@ class FlutterFormInputDateTimeController
@override
String? onValidate(
String? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {
if (value == null || value.isEmpty) {
return translator('shell.form.error.empty');
return validationMessage;
}
}

View file

@ -0,0 +1,164 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_wizard/flutter_form.dart';
import 'package:flutter_input_library/flutter_input_library.dart' as input;
class FlutterFormInputDropdown extends FlutterFormInputWidget<Object> {
const FlutterFormInputDropdown({
required super.controller,
required this.validationMessage,
this.items,
this.selectedItemBuilder,
this.value,
this.hint,
this.disabledHint,
this.onChanged,
this.onTap,
this.elevation = 8,
this.style,
this.icon,
this.iconDisabledColor,
this.iconEnabledColor,
this.iconSize = 24.0,
this.isDense = false,
this.isExpanded = false,
this.itemHeight,
this.focusColor,
this.autofocus = false,
this.dropdownColor,
this.decoration,
this.onSaved,
this.validator,
this.autovalidateMode,
this.menuMaxHeight,
this.enableFeedback,
this.alignment = Alignment.centerLeft,
this.borderRadius,
this.padding,
super.key,
super.focusNode,
super.label,
});
final List<DropdownMenuItem<Object?>>? items;
final List<Widget> Function(BuildContext)? selectedItemBuilder;
final Object? value;
final Widget? hint;
final Widget? disabledHint;
final void Function(Object?)? onChanged;
final void Function()? onTap;
final int elevation;
final TextStyle? style;
final Widget? icon;
final Color? iconDisabledColor;
final Color? iconEnabledColor;
final double iconSize;
final bool isDense;
final bool isExpanded;
final double? itemHeight;
final Color? focusColor;
final bool autofocus;
final Color? dropdownColor;
final InputDecoration? decoration;
final void Function(Object?)? onSaved;
final String? Function(Object?)? validator;
final AutovalidateMode? autovalidateMode;
final double? menuMaxHeight;
final bool? enableFeedback;
final AlignmentGeometry alignment;
final BorderRadius? borderRadius;
final EdgeInsetsGeometry? padding;
final String validationMessage;
@override
Widget build(BuildContext context) {
super.registerController(context);
return input.FlutterFormInputDropdown(
items: items,
selectedItemBuilder: selectedItemBuilder,
value: value,
hint: hint,
disabledHint: disabledHint,
onChanged: controller.onChanged,
onTap: () => onTap?.call(),
elevation: elevation,
style: style,
icon: icon,
iconDisabledColor: iconDisabledColor,
iconEnabledColor: iconEnabledColor,
iconSize: iconSize,
isDense: isDense,
isExpanded: isExpanded,
itemHeight: itemHeight,
focusColor: focusColor,
focusNode: focusNode,
autofocus: autofocus,
dropdownColor: dropdownColor,
decoration: decoration,
onSaved: controller.onSaved,
validator: validator ??
(value) => controller.onValidate(
value,
validationMessage,
),
autovalidateMode: autovalidateMode,
menuMaxHeight: menuMaxHeight,
enableFeedback: enableFeedback,
alignment: alignment,
borderRadius: borderRadius,
padding: padding,
);
}
}
class FlutterFormInputDropdownController
implements FlutterFormInputController<Object> {
FlutterFormInputDropdownController({
required this.id,
this.mandatory = false,
this.value,
this.checkPageTitle,
this.checkPageDescription,
this.onChanged,
this.onSubmit,
});
@override
String? id;
@override
Object? value;
@override
bool mandatory;
@override
String Function(Object? value)? checkPageTitle;
@override
String Function(Object? value)? checkPageDescription;
@override
void Function(Object? value)? onChanged;
@override
void Function(Object? value)? onSubmit;
@override
void onSaved(Object? value) {
this.value = value;
}
@override
String? onValidate(
Object? value,
String validationMessage,
) {
if (mandatory) {
if (value == null) {
return validationMessage;
}
}
return null;
}
}

View file

@ -10,35 +10,45 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
///
/// Standard controller is [FlutterFormInputEmailController].
class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
/// Creates a [FlutterFormInputEmail].
///
/// The [controller] parameter is required.
/// The [key], [focusNode], [label], and [enabled] parameters are optional.
const FlutterFormInputEmail({
required super.controller,
required this.validationMessage,
super.key,
super.focusNode,
super.label,
bool? enabled,
this.validator,
this.decoration,
this.style,
}) : super(
enabled: enabled ?? true,
);
final InputDecoration? decoration;
final String validationMessage;
final String? Function(String?)? validator;
final TextStyle? style;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
return input.FlutterFormInputPlainText(
style: style,
enabled: enabled,
initialValue: controller.value,
onSaved: (value) {
controller.onSaved(value);
},
focusNode: focusNode,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
onChanged: (value) => controller.onChanged?.call(value),
decoration: InputDecoration(
focusColor: Theme.of(context).primaryColor,
label: label ?? const Text('Email'),
),
decoration: decoration,
);
}
}
@ -49,6 +59,12 @@ class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
/// Mainly used by [FlutterFormInputEmail].
class FlutterFormInputEmailController
implements FlutterFormInputController<String> {
/// Creates a [FlutterFormInputEmailController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription], [onChanged],
/// and [onSubmit] parameters are optional.
FlutterFormInputEmailController({
required this.id,
this.mandatory = true,
@ -88,17 +104,17 @@ class FlutterFormInputEmailController
@override
String? onValidate(
String? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {
if (value == null || value.isEmpty) {
return translator('shell.form.error.empty');
return validationMessage;
}
if (!RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+",
).hasMatch(value)) {
return translator('shell.form.error.email.notValid');
return validationMessage;
}
}

View file

@ -15,34 +15,47 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
class FlutterFormInputNumberPicker extends FlutterFormInputWidget<int> {
const FlutterFormInputNumberPicker({
required super.controller,
required this.validationMessage,
super.key,
super.label,
this.validator,
this.minValue = 0,
this.maxValue = 100,
}) : assert(minValue < maxValue, 'minValue must be less than maxValue');
final int minValue;
final int maxValue;
final String validationMessage;
final String? Function(int?)? validator;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
return input.FlutterFormInputNumberPicker(
minValue: minValue,
maxValue: maxValue,
onSaved: controller.onSaved,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
onChanged: (value) => controller.onChanged?.call(value),
initialValue: controller.value ?? minValue,
);
}
}
/// Controller for numbers used by a [FlutterFormInputWidget] used in a
/// [FlutterForm].
///
/// Mainly used by [FlutterFormInputNumberPicker].
class FlutterFormInputNumberPickerController
implements FlutterFormInputController<int> {
/// Creates a [FlutterFormInputNumberPickerController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription],
/// and [onChanged] parameters are optional.
FlutterFormInputNumberPickerController({
required this.id,
this.mandatory = true,
@ -81,7 +94,7 @@ class FlutterFormInputNumberPickerController
@override
String? onValidate(
int? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {}

View file

@ -12,28 +12,34 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
const FlutterFormInputPassword({
required super.controller,
required this.validationMessage,
super.key,
super.focusNode,
super.label,
bool? enabled,
this.validator,
this.decoration,
}) : super(
enabled: enabled ?? true,
);
final InputDecoration? decoration;
final String validationMessage;
final String? Function(String?)? validator;
@override
Widget build(BuildContext context) {
super.registerController(context);
var _ = getTranslator(context);
return input.FlutterFormInputPassword(
enabled: enabled,
initialValue: controller.value,
focusNode: focusNode,
onSaved: controller.onSaved,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
onChanged: (value) => controller.onChanged?.call(value),
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
decoration: decoration,
);
}
}
@ -44,6 +50,12 @@ class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
/// Mainly used by [FlutterFormInputPassword].
class FlutterFormInputPasswordController
implements FlutterFormInputController<String> {
/// Creates a [FlutterFormInputPasswordController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription], [onChanged],
/// and [onSubmit] parameters are optional.
FlutterFormInputPasswordController({
required this.id,
this.mandatory = true,
@ -83,15 +95,15 @@ class FlutterFormInputPasswordController
@override
String? onValidate(
String? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {
if (value == null || value.isEmpty) {
return translator('Field can not be empty');
return validationMessage;
}
if (value.length < 6) {
return translator('Field should be atleast 6 characters long');
return validationMessage;
}
}

View file

@ -0,0 +1,116 @@
// 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,
required this.validationMessage,
super.key,
super.focusNode,
super.label,
this.decoration,
this.enabled = true,
this.numberFieldStyle,
this.validator,
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;
final String validationMessage;
final String? Function(PhoneNumber?)? validator;
@override
Widget build(BuildContext 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: validator ??
(value) => controller.onValidate(value, validationMessage),
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 validationMessage,
) {
if (mandatory) {
if (value == null || value.number == null) {
return validationMessage;
}
}
return null;
}
}

View file

@ -12,8 +12,15 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
///
/// Standard controller is [FlutterFormInputPlainTextController].
class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
/// Creates a [FlutterFormInputPlainText].
///
/// The [controller] parameter is required.
/// The [key], [focusNode], [label], [decoration], [textAlignVertical],
/// [expands], [maxLines], [scrollPadding], [maxLength], [keyboardType],
/// [enabled], [style], and [textCapitalization] parameters are optional.
const FlutterFormInputPlainText({
required super.controller,
required this.validationMessage,
super.key,
super.focusNode,
super.label,
@ -24,6 +31,7 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
this.scrollPadding,
this.maxLength,
this.keyboardType,
this.validator,
this.enabled = true,
this.style,
this.textCapitalization = TextCapitalization.none,
@ -40,11 +48,11 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
final bool enabled;
final TextStyle? style;
final TextCapitalization textCapitalization;
final String validationMessage;
final String? Function(String?)? validator;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
var inputDecoration = decoration ??
@ -59,7 +67,8 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
initialValue: controller.value,
focusNode: focusNode,
onSaved: controller.onSaved,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
onChanged: (value) => controller.onChanged?.call(value),
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
decoration: inputDecoration,
@ -83,29 +92,44 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
class FlutterFormInputMultiLine extends StatelessWidget {
const FlutterFormInputMultiLine({
required this.controller,
required this.validationMessage,
super.key,
this.focusNode,
this.label,
this.hint,
this.validator,
this.maxCharacters,
this.enabled = true,
this.textCapitalization = TextCapitalization.sentences,
});
/// The controller for the multi-line input.
final FlutterFormInputController<String> controller;
/// The optional label widget for the input.
final Widget? label;
/// The optional focus node for the input.
final FocusNode? focusNode;
/// The optional hint text displayed inside the input field.
final String? hint;
/// The optional maximum number of characters allowed in the input field.
final int? maxCharacters;
/// A flag indicating whether the input field is enabled.
final bool enabled;
/// The capitalization behavior for the input field.
final TextCapitalization textCapitalization;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
final String validationMessage;
return input.FlutterFormInputMultiLine(
final String? Function(String?)? validator;
@override
Widget build(BuildContext context) => input.FlutterFormInputMultiLine(
enabled: enabled,
label: label,
hint: hint,
@ -114,11 +138,11 @@ class FlutterFormInputMultiLine extends StatelessWidget {
maxCharacters: maxCharacters,
onChanged: controller.onChanged,
onSaved: controller.onSaved,
validator: (v) => controller.onValidate(v, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
textCapitalization: textCapitalization,
);
}
}
/// Controller for plain text used by a [FlutterFormInputWidget] used in a
/// [FlutterForm].
@ -126,6 +150,12 @@ class FlutterFormInputMultiLine extends StatelessWidget {
/// Mainly used by [FlutterFormInputPlainText].
class FlutterFormInputPlainTextController
implements FlutterFormInputController<String> {
/// Creates a [FlutterFormInputPlainTextController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription], [onChanged],
/// and [onSubmit] parameters are optional.
FlutterFormInputPlainTextController({
required this.id,
this.mandatory = false,
@ -165,11 +195,11 @@ class FlutterFormInputPlainTextController
@override
String? onValidate(
String? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {
if (value == null || value.isEmpty) {
return translator('Field can not be empty');
return validationMessage;
}
}

View file

@ -11,28 +11,37 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
///
/// Standard controller is [FlutterFormInputSliderController].
class FlutterFormInputSlider extends FlutterFormInputWidget<double> {
/// Creates a [FlutterFormInputPassword].
///
/// The [controller] parameter is required.
/// The [focusNode] parameter specifies the focus node of the input field.
/// The [label] parameter specifies the label of the input field.
/// The [enabled] parameter specifies whether the input field is enabled.
const FlutterFormInputSlider({
required super.controller,
required this.validationMessage,
super.key,
super.focusNode,
super.label,
this.validator,
this.minValue = 0,
this.maxValue = 100,
}) : assert(minValue < maxValue, 'minValue must be less than maxValue');
final int minValue;
final int maxValue;
final String validationMessage;
final String? Function(double?)? validator;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
return input.FlutterFormInputSlider(
focusNode: focusNode,
onSaved: controller.onSaved,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
);
}
}
@ -43,6 +52,12 @@ class FlutterFormInputSlider extends FlutterFormInputWidget<double> {
/// Mainly used by [FlutterFormInputSlider].
class FlutterFormInputSliderController
implements FlutterFormInputController<double> {
/// Creates a [FlutterFormInputPasswordController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription], [onChanged],
/// and [onSubmit] parameters are optional.
FlutterFormInputSliderController({
required this.id,
this.mandatory = true,
@ -81,7 +96,7 @@ class FlutterFormInputSliderController
@override
String? onValidate(
double? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) {
if (mandatory) {}

View file

@ -14,22 +14,26 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
const FlutterFormInputSwitch({
required super.controller,
required this.validationMessage,
super.key,
super.focusNode,
super.label,
this.validator,
});
final String validationMessage;
final String? Function(bool?)? validator;
@override
Widget build(BuildContext context) {
var _ = getTranslator(context);
super.registerController(context);
return input.FlutterFormInputBool(
focusNode: focusNode,
onSaved: controller.onSaved,
onChanged: controller.onChanged,
validator: (value) => controller.onValidate(value, _),
validator: validator ??
(value) => controller.onValidate(value, validationMessage),
initialValue: controller.value ?? false,
widgetType: input.BoolWidgetType.switchWidget,
);
@ -42,6 +46,12 @@ class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
/// Mainly used by [FlutterFormInputSwitch].
class FlutterFormInputSwitchController
implements FlutterFormInputController<bool> {
/// Creates a [FlutterFormInputSwitchController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription],
/// and [onChanged] parameters are optional.
FlutterFormInputSwitchController({
required this.id,
this.mandatory = true,
@ -80,7 +90,7 @@ class FlutterFormInputSwitchController
@override
String? onValidate(
bool? value,
String Function(String, {List<String>? params}) translator,
String validationMessage,
) =>
null;
}

View file

@ -2,11 +2,17 @@
//
// 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_dropdown.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';
export 'multiple_choice.dart';

View file

@ -0,0 +1,159 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_wizard/flutter_form.dart';
class FlutterFormInputMultipleChoice extends FlutterFormInputWidget<String> {
/// Creates a [FlutterFormInputMultipleChoice].
///
/// The [controller], [options], [builder], [validationMessage] parameters
/// are required.
/// The [key], [focusNode], [label] are optional.
const FlutterFormInputMultipleChoice({
required super.controller,
required this.options,
required this.builder,
required this.validationMessage,
super.focusNode,
super.label,
super.key,
this.mainAxisExtent,
this.childAspectRatio = 1,
this.mainAxisSpacing = 0,
this.crossAxisSpacing = 0,
this.crossAxisCount = 3,
this.height,
this.shrinkwrap = true,
this.validator,
});
final List<String> options;
final double? mainAxisExtent;
final double childAspectRatio;
final double mainAxisSpacing;
final double crossAxisSpacing;
final int crossAxisCount;
final double? height;
final bool shrinkwrap;
final Widget Function(
BuildContext context,
int index,
ValueNotifier<int?> selectedIndex,
FlutterFormInputController controller,
List<String> options,
FormFieldState<String> state,
) builder;
final String? Function(String? value, String validationMessage)? validator;
final String validationMessage;
@override
Widget build(BuildContext context) {
super.registerController(context);
var selectedIndex = ValueNotifier<int?>(null);
return FormField<String>(
onSaved: controller.onSaved,
validator: (value) =>
validator?.call(value, validationMessage) ??
controller.onValidate(value, validationMessage),
builder: (state) => SizedBox(
height: height,
child: Column(
children: [
GridView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: options.length,
shrinkWrap: shrinkwrap,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisExtent: mainAxisExtent,
childAspectRatio: childAspectRatio,
mainAxisSpacing: mainAxisSpacing,
crossAxisSpacing: crossAxisSpacing,
crossAxisCount: crossAxisCount,
),
itemBuilder: (context, index) => ListenableBuilder(
listenable: selectedIndex,
builder: (context, widget) => builder.call(
context,
index,
selectedIndex,
controller,
options,
state,
),
),
),
if (state.hasError)
Text(
state.errorText!,
style: const TextStyle(
color: Color(0xFFAD3645),
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
)
else
const SizedBox.shrink(),
],
),
),
);
}
}
class FlutterFormInputMultipleChoiceController
implements FlutterFormInputController<String> {
/// Creates a [FlutterFormInputMultipleChoiceController].
///
/// The [id] parameter specifies the unique identifier for the controller.
/// The [mandatory] parameter specifies whether the input is mandatory.
/// The [value], [checkPageTitle], [checkPageDescription], [onChanged],
/// and [onSubmit] parameters are optional.
FlutterFormInputMultipleChoiceController({
required this.id,
this.mandatory = false,
this.value,
this.checkPageTitle,
this.checkPageDescription,
this.onChanged,
this.onSubmit,
});
@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 Function(String? value)? onSubmit;
@override
void onSaved(String? value) {
this.value = value;
}
@override
String? onValidate(
String? value,
String validationMessage,
) {
if (mandatory) {
if (value == null || value.isEmpty) {
return validationMessage;
}
}
return null;
}
}

View file

@ -22,6 +22,7 @@ import 'package:flutter/material.dart';
///
/// [onFinished] and [onNext] are both callbacks which give the users results.
/// [onNext] is called when the user goes to the next page.
/// [onBack] is called when the user goes back a page.
/// [onFinished] is called when the form is finished. When checkpage is set
/// [onFinished] is called when the checkpage is finished.
///
@ -35,6 +36,7 @@ class FlutterFormOptions {
required this.pages,
required this.onFinished,
required this.onNext,
this.onBack,
this.checkPage,
this.nextButton,
this.backButton,
@ -49,6 +51,11 @@ class FlutterFormOptions {
backButton;
final void Function(Map<int, Map<String, dynamic>>) onFinished;
final void Function(int pageNumber, Map<String, dynamic>) onNext;
/// [onBack] is called when the user goes back a page. The [pageNumber] is the
/// page the user is going back to. Not the page that the user was on when the
/// user pressed the back button.
final void Function(int pageNumber)? onBack;
final Axis scrollDirection;
final ScrollPhysics? scrollPhysics;
}

View file

@ -1,48 +0,0 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
abstract class TranslationService {
TranslationService._();
String translate(
BuildContext context,
String key, {
List<String>? params,
});
String number(double value);
}
typedef Translator = String Function(
String, {
List<String>? params,
});
class ShellTranslationService implements TranslationService {
@override
String number(double value) => value.toStringAsFixed(2);
@override
String translate(BuildContext context, String key, {List<String>? params}) =>
key;
}
Translator getTranslator(BuildContext context) {
try {
var translator = ShellTranslationService().translate;
return (
String key, {
List<String>? params,
}) =>
translator(context, key, params: params);
} on Exception catch (_) {
return (
String key, {
List<String>? params,
}) =>
key;
}
}

View file

@ -1,12 +1,12 @@
name: flutter_form_wizard
description: A new Flutter package project.
version: 6.2.4
version: 6.6.0
homepage: https://github.com/Iconica-Development/flutter_form_wizard
publish_to: none
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: ">=2.18.0 <3.0.0"
sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.17.0"
dependencies:
@ -14,11 +14,10 @@ dependencies:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.18.0
intl: ">=0.18.0 <1.0.0"
flutter_input_library:
git:
url: https://github.com/Iconica-Development/flutter_input_library
ref: 3.0.1
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: ^3.4.0
dev_dependencies:
flutter_test:
@ -28,4 +27,3 @@ dev_dependencies:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 6.0.0
flutter:

View file

@ -56,6 +56,7 @@ void main() {
child: FlutterFormInputPlainText(
label: const Text('Field1Label'),
controller: testField1Controller,
validationMessage: 'Please fill in this field',
),
),
),
@ -64,6 +65,7 @@ void main() {
child: FlutterFormInputPlainText(
label: const Text('Field2Label'),
controller: testField2Controller,
validationMessage: 'Please fill in this field',
),
),
),
@ -154,6 +156,7 @@ void main() {
child: FlutterFormInputPlainText(
label: const Text('Field1Label'),
controller: testField1Controller,
validationMessage: 'Please fill in this field',
),
),
),
@ -162,6 +165,7 @@ void main() {
child: FlutterFormInputPlainText(
label: const Text('Field2Label'),
controller: testField2Controller,
validationMessage: 'Please fill in this field',
),
),
),
@ -260,6 +264,7 @@ void main() {
child: FlutterFormInputPlainText(
label: const Text('Field1Label'),
controller: testField1Controller,
validationMessage: 'Field can not be empty',
),
),
),