mirror of
https://github.com/Iconica-Development/flutter_form_wizard.git
synced 2025-05-19 10:53:49 +02:00
Merge branch 'fix/add_ci_linter'
This commit is contained in:
commit
650418a36f
23 changed files with 417 additions and 374 deletions
14
.github/workflows/component-ci.yml
vendored
Normal file
14
.github/workflows/component-ci.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: Iconica Standard Component CI Workflow
|
||||||
|
# Workflow Caller version: 2.0.0
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-global-iconica-workflow:
|
||||||
|
uses: Iconica-Development/.github/.github/workflows/component-ci.yml@master
|
||||||
|
secrets: inherit
|
||||||
|
permissions: write-all
|
||||||
|
with:
|
||||||
|
subfolder: "." # add optional subfolder to run workflow in
|
32
.github/workflows/flutter.yml
vendored
32
.github/workflows/flutter.yml
vendored
|
@ -1,32 +0,0 @@
|
||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- feature/*
|
|
||||||
- bugfix/*
|
|
||||||
- hotfix/*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/wrapper
|
|
||||||
/opt/hostedtoolcache/flutter
|
|
||||||
key: ${{ runner.OS }}-flutter-install-cache
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
channel: "stable"
|
|
||||||
- name: Flutter pub get
|
|
||||||
run: flutter pub get
|
|
||||||
- name: Dart format
|
|
||||||
run: dart format -o none --set-exit-if-changed .
|
|
||||||
- name: Flutter analyze
|
|
||||||
run: flutter analyze
|
|
|
@ -114,4 +114,8 @@
|
||||||
- Pass on the `initialValue` property to FlutterFormMultiLine
|
- Pass on the `initialValue` property to FlutterFormMultiLine
|
||||||
|
|
||||||
## 6.2.2 - February 6th 2024
|
## 6.2.2 - February 6th 2024
|
||||||
- Updated the `flutter_input_library` from 2.6.0 to 3.0.0
|
- Updated the `flutter_input_library` from 2.6.0 to 3.0.0
|
||||||
|
|
||||||
|
## 6.2.3 - February 7th 2024
|
||||||
|
|
||||||
|
- Added CI and linter
|
|
@ -1,4 +1,9 @@
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_iconica_analysis/analysis_options.yaml
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
# Possible to overwrite the rules from the package
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
|
|
@ -68,7 +68,7 @@ packages:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "6.2.1"
|
version: "6.2.2"
|
||||||
flutter_input_library:
|
flutter_input_library:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
export 'package:flutter_input_library/flutter_input_library.dart'
|
||||||
|
show FlutterFormDateTimeType;
|
||||||
|
|
||||||
export 'src/form.dart';
|
export 'src/form.dart';
|
||||||
export 'src/widgets/input/abstractions.dart';
|
export 'src/widgets/input/abstractions.dart';
|
||||||
export 'src/widgets/input/input_types/input_types.dart';
|
export 'src/widgets/input/input_types/input_types.dart';
|
||||||
export 'package:flutter_input_library/flutter_input_library.dart'
|
|
||||||
show FlutterFormDateTimeType;
|
|
||||||
export 'utils/translation_service.dart';
|
|
||||||
export 'utils/form.dart';
|
export 'utils/form.dart';
|
||||||
|
export 'utils/translation_service.dart';
|
||||||
|
|
|
@ -3,18 +3,23 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../flutter_form.dart';
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'utils/form_page_controller.dart';
|
import 'package:flutter_form_wizard/src/utils/form_page_controller.dart';
|
||||||
import 'utils/formstate.dart' as fs;
|
import 'package:flutter_form_wizard/src/utils/formstate.dart' as fs;
|
||||||
|
|
||||||
/// A wrapper for flutters [Form] that can be controlled by a controller and provides multiple pre-defined input types/fields
|
/// A wrapper for flutters [Form] that can be controlled by a controller and
|
||||||
/// [FlutterForm] also provides multi page forms and a check page for validation.
|
/// provides multiple pre-defined input types/fields
|
||||||
|
/// [FlutterForm] also provides multi page forms and a check page
|
||||||
|
/// for validation.
|
||||||
///
|
///
|
||||||
/// A [FlutterFormController] has to be given to control what happens to values and pages within the FlutterForm.
|
/// A [FlutterFormController] has to be given to control what happens to values
|
||||||
|
/// and pages within the FlutterForm.
|
||||||
///
|
///
|
||||||
/// [FlutterFormOptions] have to be provided to control the appearance of the form.
|
/// [FlutterFormOptions] have to be provided to control the appearance of
|
||||||
|
/// the form.
|
||||||
///
|
///
|
||||||
/// WARNING Define your FormInputController above your FlutterForm. Otherwise when rebuild the controller will differ from the registered ones.
|
/// WARNING Define your FormInputController above your FlutterForm. Otherwise
|
||||||
|
/// when rebuild the controller will differ from the registered ones.
|
||||||
/// ``` dart
|
/// ``` dart
|
||||||
/// FlutterFormInputEmailController emailController =
|
/// FlutterFormInputEmailController emailController =
|
||||||
/// FlutterFormInputEmailController(id: 'email');
|
/// FlutterFormInputEmailController(id: 'email');
|
||||||
|
@ -180,10 +185,10 @@ import 'utils/formstate.dart' as fs;
|
||||||
/// ```
|
/// ```
|
||||||
class FlutterForm extends StatefulWidget {
|
class FlutterForm extends StatefulWidget {
|
||||||
const FlutterForm({
|
const FlutterForm({
|
||||||
Key? key,
|
|
||||||
required this.options,
|
required this.options,
|
||||||
required this.formController,
|
required this.formController,
|
||||||
}) : super(key: key);
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final FlutterFormOptions options;
|
final FlutterFormOptions options;
|
||||||
final FlutterFormController formController;
|
final FlutterFormController formController;
|
||||||
|
@ -203,9 +208,9 @@ class _FlutterFormState extends State<FlutterForm> {
|
||||||
|
|
||||||
_formController.setFlutterFormOptions(widget.options);
|
_formController.setFlutterFormOptions(widget.options);
|
||||||
|
|
||||||
List<GlobalKey<FormState>> keys = [];
|
var keys = <GlobalKey<FormState>>[];
|
||||||
|
|
||||||
for (FlutterFormPage _ in widget.options.pages) {
|
for (var _ in widget.options.pages) {
|
||||||
keys.add(GlobalKey<FormState>());
|
keys.add(GlobalKey<FormState>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,9 +220,9 @@ class _FlutterFormState extends State<FlutterForm> {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
|
|
||||||
List<FlutterFormPageController> controllers = [];
|
var controllers = <FlutterFormPageController>[];
|
||||||
|
|
||||||
for (int i = 0; i < widget.options.pages.length; i++) {
|
for (var i = 0; i < widget.options.pages.length; i++) {
|
||||||
controllers.add(FlutterFormPageController());
|
controllers.add(FlutterFormPageController());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,27 +283,37 @@ class _FlutterFormState extends State<FlutterForm> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
widget.options.nextButton != null
|
if (widget.options.nextButton != null)
|
||||||
? widget.options.nextButton!(_formController.getCurrentStep(),
|
widget.options.nextButton!(
|
||||||
_formController.getCheckpages())
|
_formController.getCurrentStep(),
|
||||||
: Align(
|
_formController.getCheckpages(),
|
||||||
alignment: AlignmentDirectional.bottomCenter,
|
)
|
||||||
child: ElevatedButton(
|
else
|
||||||
style: ElevatedButton.styleFrom(
|
Align(
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
alignment: AlignmentDirectional.bottomCenter,
|
||||||
padding: const EdgeInsets.symmetric(
|
child: ElevatedButton(
|
||||||
horizontal: 40, vertical: 15),
|
style: ElevatedButton.styleFrom(
|
||||||
textStyle: const TextStyle(
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
fontSize: 20, fontWeight: FontWeight.bold)),
|
padding: const EdgeInsets.symmetric(
|
||||||
onPressed: () async {
|
horizontal: 40,
|
||||||
await _formController.autoNextStep();
|
vertical: 15,
|
||||||
},
|
),
|
||||||
child: Text(_formController.getCurrentStep() >=
|
textStyle: const TextStyle(
|
||||||
widget.options.pages.length - 1
|
fontSize: 20,
|
||||||
? "Finish"
|
fontWeight: FontWeight.bold,
|
||||||
: "Next"),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
await _formController.autoNextStep();
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
_formController.getCurrentStep() >=
|
||||||
|
widget.options.pages.length - 1
|
||||||
|
? 'Finish'
|
||||||
|
: 'Next',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
if (widget.options.backButton != null)
|
if (widget.options.backButton != null)
|
||||||
widget.options.backButton!(
|
widget.options.backButton!(
|
||||||
_formController.getCurrentStep(),
|
_formController.getCurrentStep(),
|
||||||
|
@ -310,12 +325,12 @@ class _FlutterFormState extends State<FlutterForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> getResultWidgets() {
|
List<Widget> getResultWidgets() {
|
||||||
List<Widget> widgets = [];
|
var widgets = <Widget>[];
|
||||||
|
|
||||||
_formController.getAllResults().forEach(
|
_formController.getAllResults().forEach(
|
||||||
(pageNumber, pageResults) {
|
(pageNumber, pageResults) {
|
||||||
pageResults.forEach((inputId, inputResult) {
|
pageResults.forEach((inputId, inputResult) {
|
||||||
FlutterFormInputController? inputController = _formController
|
var inputController = _formController
|
||||||
.getFormPageControllers()[pageNumber]
|
.getFormPageControllers()[pageNumber]
|
||||||
.getController(inputId);
|
.getController(inputId);
|
||||||
|
|
||||||
|
@ -327,10 +342,8 @@ class _FlutterFormState extends State<FlutterForm> {
|
||||||
inputController.checkPageTitle != null
|
inputController.checkPageTitle != null
|
||||||
? inputController.checkPageTitle!(inputController.value)
|
? inputController.checkPageTitle!(inputController.value)
|
||||||
: inputController.value.toString(),
|
: inputController.value.toString(),
|
||||||
inputController.checkPageDescription != null
|
inputController.checkPageDescription
|
||||||
? inputController
|
?.call(inputController.value),
|
||||||
.checkPageDescription!(inputController.value)
|
|
||||||
: null,
|
|
||||||
() async {
|
() async {
|
||||||
await _formController.jumpToPage(pageNumber);
|
await _formController.jumpToPage(pageNumber);
|
||||||
},
|
},
|
||||||
|
@ -378,7 +391,7 @@ class _FlutterFormState extends State<FlutterForm> {
|
||||||
Text(
|
Text(
|
||||||
inputController.checkPageDescription!(inputResult),
|
inputController.checkPageDescription!(inputResult),
|
||||||
style: const TextStyle(fontSize: 16),
|
style: const TextStyle(fontSize: 16),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -412,15 +425,14 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
|
|
||||||
late List<FlutterFormPageController> _formPageControllers;
|
late List<FlutterFormPageController> _formPageControllers;
|
||||||
|
|
||||||
List<FlutterFormPageController> getFormPageControllers() {
|
List<FlutterFormPageController> getFormPageControllers() =>
|
||||||
return _formPageControllers;
|
_formPageControllers;
|
||||||
}
|
|
||||||
|
|
||||||
setFormPageControllers(List<FlutterFormPageController> controllers) {
|
void setFormPageControllers(List<FlutterFormPageController> controllers) {
|
||||||
_formPageControllers = controllers;
|
_formPageControllers = controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
disableCheckingPages() {
|
void voidisableCheckingPages() {
|
||||||
_checkingPages = false;
|
_checkingPages = false;
|
||||||
|
|
||||||
for (var controller in _formPageControllers) {
|
for (var controller in _formPageControllers) {
|
||||||
|
@ -436,7 +448,9 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
FocusManager.instance.primaryFocus?.unfocus();
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
|
||||||
_options.onNext(
|
_options.onNext(
|
||||||
_currentStep, _formPageControllers[_currentStep].getAllValues());
|
_currentStep,
|
||||||
|
_formPageControllers[_currentStep].getAllValues(),
|
||||||
|
);
|
||||||
|
|
||||||
if (_currentStep >= _options.pages.length - 1 &&
|
if (_currentStep >= _options.pages.length - 1 &&
|
||||||
_options.checkPage == null ||
|
_options.checkPage == null ||
|
||||||
|
@ -449,9 +463,11 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
await _pageController.animateToPage(_currentStep,
|
await _pageController.animateToPage(
|
||||||
duration: const Duration(milliseconds: 250),
|
_currentStep,
|
||||||
curve: Curves.ease);
|
duration: const Duration(milliseconds: 250),
|
||||||
|
curve: Curves.ease,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
_currentStep += 1;
|
_currentStep += 1;
|
||||||
|
|
||||||
|
@ -462,9 +478,11 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
await _pageController.animateToPage(_currentStep,
|
await _pageController.animateToPage(
|
||||||
duration: const Duration(milliseconds: 250),
|
_currentStep,
|
||||||
curve: Curves.ease);
|
duration: const Duration(milliseconds: 250),
|
||||||
|
curve: Curves.ease,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,13 +525,14 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> getCurrentStepResults() {
|
Map<String, dynamic> getCurrentStepResults() =>
|
||||||
return _formPageControllers[_currentStep].getAllValues();
|
_formPageControllers[_currentStep].getAllValues();
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> nextStep() async {
|
Future<void> nextStep() async {
|
||||||
_options.onNext(
|
_options.onNext(
|
||||||
_currentStep, _formPageControllers[_currentStep].getAllValues());
|
_currentStep,
|
||||||
|
_formPageControllers[_currentStep].getAllValues(),
|
||||||
|
);
|
||||||
|
|
||||||
_currentStep += 1;
|
_currentStep += 1;
|
||||||
|
|
||||||
|
@ -523,16 +542,19 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
await _pageController.animateToPage(_currentStep,
|
await _pageController.animateToPage(
|
||||||
duration: const Duration(milliseconds: 250), curve: Curves.ease);
|
_currentStep,
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
curve: Curves.ease,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
finishForm() {
|
void finishForm() {
|
||||||
_options.onFinished(getAllResults());
|
_options.onFinished(getAllResults());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<int, Map<String, dynamic>> getAllResults() {
|
Map<int, Map<String, dynamic>> getAllResults() {
|
||||||
Map<int, Map<String, dynamic>> allValues = {};
|
var allValues = <int, Map<String, dynamic>>{};
|
||||||
|
|
||||||
for (var i = 0; i < _options.pages.length; i++) {
|
for (var i = 0; i < _options.pages.length; i++) {
|
||||||
allValues.addAll({i: _formPageControllers[i].getAllValues()});
|
allValues.addAll({i: _formPageControllers[i].getAllValues()});
|
||||||
|
@ -540,27 +562,19 @@ class FlutterFormController extends ChangeNotifier {
|
||||||
return allValues;
|
return allValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFlutterFormOptions(FlutterFormOptions options) {
|
void setFlutterFormOptions(FlutterFormOptions options) {
|
||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
setKeys(List<GlobalKey<FormState>> keys) {
|
void setKeys(List<GlobalKey<FormState>> keys) {
|
||||||
_keys = keys;
|
_keys = keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<GlobalKey<FormState>> getKeys() {
|
List<GlobalKey<FormState>> getKeys() => _keys;
|
||||||
return _keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getCurrentStep() {
|
int getCurrentStep() => _currentStep;
|
||||||
return _currentStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getCheckpages() {
|
bool getCheckpages() => _checkingPages;
|
||||||
return _checkingPages;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController getPageController() {
|
PageController getPageController() => _pageController;
|
||||||
return _pageController;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,12 @@ class FlutterFormPageController {
|
||||||
_controllers.add(inputController);
|
_controllers.add(inputController);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearControllers() {
|
void clearControllers() {
|
||||||
_controllers = [];
|
_controllers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isRegisteredById(String id) {
|
bool _isRegisteredById(String id) =>
|
||||||
return _controllers.any((element) => (element.id == id));
|
_controllers.any((element) => element.id == id);
|
||||||
}
|
|
||||||
|
|
||||||
FlutterFormInputController? getController(String key) {
|
FlutterFormInputController? getController(String key) {
|
||||||
if (_isRegisteredById(key)) {
|
if (_isRegisteredById(key)) {
|
||||||
|
@ -27,9 +26,9 @@ class FlutterFormPageController {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> getAllValues() {
|
Map<String, dynamic> getAllValues() {
|
||||||
Map<String, dynamic> values = {};
|
var values = <String, dynamic>{};
|
||||||
|
|
||||||
for (FlutterFormInputController controller in _controllers) {
|
for (var controller in _controllers) {
|
||||||
if (controller.value != null) {
|
if (controller.value != null) {
|
||||||
values.addAll({controller.id!: controller.value});
|
values.addAll({controller.id!: controller.value});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,19 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'form_page_controller.dart';
|
import 'package:flutter_form_wizard/src/utils/form_page_controller.dart';
|
||||||
|
|
||||||
class FormState extends InheritedWidget {
|
class FormState extends InheritedWidget {
|
||||||
const FormState({
|
const FormState({
|
||||||
Key? key,
|
required super.child,
|
||||||
required Widget child,
|
|
||||||
required this.formController,
|
required this.formController,
|
||||||
}) : super(key: key, child: child);
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final FlutterFormPageController formController;
|
final FlutterFormPageController formController;
|
||||||
|
|
||||||
static FormState of(BuildContext context) {
|
static FormState of(BuildContext context) {
|
||||||
final FormState? result =
|
var result = context.dependOnInheritedWidgetOfExactType<FormState>();
|
||||||
context.dependOnInheritedWidgetOfExactType<FormState>();
|
|
||||||
assert(result != null, 'No FormStat found in context');
|
assert(result != null, 'No FormStat found in context');
|
||||||
return result!;
|
return result!;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '/src/utils/formstate.dart' as fs;
|
import 'package:flutter_form_wizard/src/utils/formstate.dart' as fs;
|
||||||
|
|
||||||
/// Abstract class for the input widgets used in a [FlutterForm].
|
/// Abstract class for the input widgets used in a [FlutterForm].
|
||||||
///
|
///
|
||||||
|
@ -12,18 +12,19 @@ import '/src/utils/formstate.dart' as fs;
|
||||||
///
|
///
|
||||||
/// label is a standard parameter to normally sets the label of the input.
|
/// label is a standard parameter to normally sets the label of the input.
|
||||||
///
|
///
|
||||||
/// [registerController] should be called to register the given [controller] to the form page.
|
/// [registerController] should be called to register the given [controller] to
|
||||||
|
/// the form page.
|
||||||
abstract class FlutterFormInputWidget<T> extends StatelessWidget {
|
abstract class FlutterFormInputWidget<T> extends StatelessWidget {
|
||||||
const FlutterFormInputWidget({
|
const FlutterFormInputWidget({
|
||||||
Key? key,
|
|
||||||
required this.controller,
|
required this.controller,
|
||||||
|
super.key,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
this.label,
|
this.label,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
String? hintText,
|
});
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
/// The [controller] which determines how the value is handled and how the value is shown on the checkpage.
|
/// The [controller] which determines how the value is handled and how the
|
||||||
|
/// value is shown on the checkpage.
|
||||||
final FlutterFormInputController<T> controller;
|
final FlutterFormInputController<T> controller;
|
||||||
|
|
||||||
/// [label] is a standard parameter to normally sets the label of the input.
|
/// [label] is a standard parameter to normally sets the label of the input.
|
||||||
|
@ -33,9 +34,10 @@ abstract class FlutterFormInputWidget<T> extends StatelessWidget {
|
||||||
|
|
||||||
final bool enabled;
|
final bool enabled;
|
||||||
|
|
||||||
/// [registerController] should be called to register the given [controller] to the form page.
|
/// [registerController] should be called to register the given [controller]
|
||||||
registerController(BuildContext context) {
|
/// to the form page.
|
||||||
FlutterFormInputController? localController =
|
void registerController(BuildContext context) {
|
||||||
|
var localController =
|
||||||
fs.FormState.of(context).formController.getController(controller.id!);
|
fs.FormState.of(context).formController.getController(controller.id!);
|
||||||
|
|
||||||
if (localController == null) {
|
if (localController == null) {
|
||||||
|
@ -48,11 +50,13 @@ abstract class FlutterFormInputWidget<T> extends StatelessWidget {
|
||||||
///
|
///
|
||||||
/// The [id] determines the key in the [Map] returned by the [FlutterForm].
|
/// The [id] determines the key in the [Map] returned by the [FlutterForm].
|
||||||
///
|
///
|
||||||
/// [value] is a way to set a initial value and will be the value when change by the user.
|
/// [value] is a way to set a initial value and will be the value when change
|
||||||
|
/// by the user.
|
||||||
///
|
///
|
||||||
/// [mandatory] determines if the input is mandatory.
|
/// [mandatory] determines if the input is mandatory.
|
||||||
///
|
///
|
||||||
/// [checkPageTitle] is a function where you can transform the value from the input into something representable.
|
/// [checkPageTitle] is a function where you can transform the value from the
|
||||||
|
/// input into something representable.
|
||||||
/// This value will be given when defining the check page widgets.
|
/// This value will be given when defining the check page widgets.
|
||||||
/// If this function is not set, the value will be used as is.
|
/// If this function is not set, the value will be used as is.
|
||||||
/// Example:
|
/// Example:
|
||||||
|
@ -62,27 +66,32 @@ abstract class FlutterFormInputWidget<T> extends StatelessWidget {
|
||||||
/// },
|
/// },
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [checkPageDescription] is the same as checkPageTitle but for the description.
|
/// [checkPageDescription] is the same as checkPageTitle but for the
|
||||||
/// If null no description will be shown.
|
/// description. If null no description will be shown.
|
||||||
///
|
///
|
||||||
/// [onChanged] can be set to get the value whenever the user changes it. Should not be used to save the value.
|
/// [onChanged] can be set to get the value whenever the user changes it.
|
||||||
|
/// Should not be used to save the value.
|
||||||
///
|
///
|
||||||
/// [onSubmit] can be set to get the value whenever the user submits it. Should not be used to save the value.
|
/// [onSubmit] can be set to get the value whenever the user submits it.
|
||||||
|
/// Should not be used to save the value.
|
||||||
///
|
///
|
||||||
/// [onSaved] goes of when the save function is called for the page if [onValidate] return null.
|
/// [onSaved] goes of when the save function is called for the page if
|
||||||
|
/// [onValidate] return null.
|
||||||
///
|
///
|
||||||
/// [onValidate] is used to validate the given input by the user.
|
/// [onValidate] is used to validate the given input by the user.
|
||||||
abstract class FlutterFormInputController<T> {
|
abstract class FlutterFormInputController<T> {
|
||||||
/// The [id] determines the key in the [Map] returned by the [FlutterForm].
|
/// The [id] determines the key in the [Map] returned by the [FlutterForm].
|
||||||
String? id;
|
String? id;
|
||||||
|
|
||||||
/// [value] is a way to set a initial value and will be the value when change by the user.
|
/// [value] is a way to set a initial value and will be the value when
|
||||||
|
/// change by the user.
|
||||||
T? value;
|
T? value;
|
||||||
|
|
||||||
/// [mandatory] determines if the input is mandatory.
|
/// [mandatory] determines if the input is mandatory.
|
||||||
bool mandatory = false;
|
bool mandatory = false;
|
||||||
|
|
||||||
/// [checkPageTitle] is a function where you can transform the value from the input into something representable.
|
/// [checkPageTitle] is a function where you can transform the value from the
|
||||||
|
/// input into something representable.
|
||||||
/// This value will be given when defining the check page widgets.
|
/// This value will be given when defining the check page widgets.
|
||||||
/// If this function is not set, the value will be used as is.
|
/// If this function is not set, the value will be used as is.
|
||||||
/// Example:
|
/// Example:
|
||||||
|
@ -93,20 +102,26 @@ abstract class FlutterFormInputController<T> {
|
||||||
/// ```
|
/// ```
|
||||||
String Function(T? value)? checkPageTitle;
|
String Function(T? value)? checkPageTitle;
|
||||||
|
|
||||||
/// [checkPageDescription] is the same as checkPageTitle but for the description.
|
/// [checkPageDescription] is the same as checkPageTitle but for the
|
||||||
|
/// description.
|
||||||
/// If null no description will be shown.
|
/// If null no description will be shown.
|
||||||
String Function(T? value)? checkPageDescription;
|
String Function(T? value)? checkPageDescription;
|
||||||
|
|
||||||
/// [onChanged] can be set to get the value whenever the user changes it. Should not be used to save the value.
|
/// [onChanged] can be set to get the value whenever the user changes it.
|
||||||
|
/// Should not be used to save the value.
|
||||||
void Function(T? value)? onChanged;
|
void Function(T? value)? onChanged;
|
||||||
|
|
||||||
/// [onSubmit] can be set to get the value whenever the user submits it. Should not be used to save the value.
|
/// [onSubmit] can be set to get the value whenever the user submits it.
|
||||||
|
/// Should not be used to save the value.
|
||||||
void Function(T? value)? onSubmit;
|
void Function(T? value)? onSubmit;
|
||||||
|
|
||||||
/// [onSaved] goes of when the save function is called for the page if [onValidate] return null.
|
/// [onSaved] goes of when the save function is called for the page if
|
||||||
|
/// [onValidate] return null.
|
||||||
void onSaved(T? value);
|
void onSaved(T? value);
|
||||||
|
|
||||||
/// [onValidate] is used to validate the given input by the user.
|
/// [onValidate] is used to validate the given input by the user.
|
||||||
String? onValidate(
|
String? onValidate(
|
||||||
T? value, String Function(String, {List<String>? params}) translator);
|
T? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,24 +15,24 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
/// Height sets the height of the inputfield. Default to 425.
|
/// Height sets the height of the inputfield. Default to 425.
|
||||||
class FlutterFormInputCarousel extends FlutterFormInputWidget<int> {
|
class FlutterFormInputCarousel extends FlutterFormInputWidget<int> {
|
||||||
const FlutterFormInputCarousel({
|
const FlutterFormInputCarousel({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<int> controller,
|
|
||||||
Widget? label,
|
|
||||||
required this.items,
|
required this.items,
|
||||||
|
super.key,
|
||||||
|
super.label,
|
||||||
this.height = 425,
|
this.height = 425,
|
||||||
}) : super(key: key, controller: controller, label: label);
|
});
|
||||||
|
|
||||||
final List<Widget> items;
|
final List<Widget> items;
|
||||||
final double height;
|
final double height;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
return input.FlutterFormInputCarousel(
|
return input.FlutterFormInputCarousel(
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
onChanged: controller.onChanged,
|
onChanged: controller.onChanged,
|
||||||
initialValue: controller.value ?? 0,
|
initialValue: controller.value ?? 0,
|
||||||
|
@ -42,7 +42,8 @@ class FlutterFormInputCarousel extends FlutterFormInputWidget<int> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for the carousel used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
/// Controller for the carousel used by a [FlutterFormInputWidget] used in
|
||||||
|
/// a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputCarousel].
|
/// Mainly used by [FlutterFormInputCarousel].
|
||||||
class FlutterFormInputCarouselController
|
class FlutterFormInputCarouselController
|
||||||
|
@ -84,7 +85,9 @@ class FlutterFormInputCarouselController
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(
|
String? onValidate(
|
||||||
int? value, String Function(String, {List<String>? params}) translator) {
|
int? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {}
|
if (mandatory) {}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -5,22 +5,21 @@
|
||||||
// ignore_for_file: overridden_fields, annotate_overrides
|
// ignore_for_file: overridden_fields, annotate_overrides
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import '../../../../../flutter_form.dart';
|
|
||||||
|
|
||||||
/// Input for a dateTime used in a [FlutterForm].
|
/// Input for a dateTime used in a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Standard controller is [FlutterFormInputDateController].
|
/// Standard controller is [FlutterFormInputDateController].
|
||||||
class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
||||||
const FlutterFormInputDateTime({
|
const FlutterFormInputDateTime({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<String> controller,
|
|
||||||
Widget? label,
|
|
||||||
this.showIcon = true,
|
|
||||||
required this.inputType,
|
required this.inputType,
|
||||||
required this.dateFormat,
|
required this.dateFormat,
|
||||||
|
super.key,
|
||||||
|
super.label,
|
||||||
|
this.showIcon = true,
|
||||||
this.firstDate,
|
this.firstDate,
|
||||||
this.lastDate,
|
this.lastDate,
|
||||||
this.initialDate,
|
this.initialDate,
|
||||||
|
@ -28,11 +27,7 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
||||||
this.icon = Icons.calendar_today,
|
this.icon = Icons.calendar_today,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
this.onTapEnabled = true,
|
this.onTapEnabled = true,
|
||||||
}) : super(
|
});
|
||||||
key: key,
|
|
||||||
controller: controller,
|
|
||||||
label: label,
|
|
||||||
);
|
|
||||||
final bool showIcon;
|
final bool showIcon;
|
||||||
final input.FlutterFormDateTimeType inputType;
|
final input.FlutterFormDateTimeType inputType;
|
||||||
final DateFormat dateFormat;
|
final DateFormat dateFormat;
|
||||||
|
@ -46,7 +41,7 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
return input.FlutterFormInputDateTime(
|
return input.FlutterFormInputDateTime(
|
||||||
|
@ -59,7 +54,7 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
||||||
lastDate: lastDate,
|
lastDate: lastDate,
|
||||||
inputType: inputType,
|
inputType: inputType,
|
||||||
onChanged: (value) => controller.onChanged?.call(value),
|
onChanged: (value) => controller.onChanged?.call(value),
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
initialValue: controller.value,
|
initialValue: controller.value,
|
||||||
dateFormat: dateFormat,
|
dateFormat: dateFormat,
|
||||||
|
@ -69,21 +64,22 @@ class FlutterFormInputDateTime extends FlutterFormInputWidget<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for dates used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
/// Controller for dates used by a [FlutterFormInputWidget] used in a
|
||||||
|
/// [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputDateTime].
|
/// Mainly used by [FlutterFormInputDateTime].
|
||||||
class FlutterFormInputDateTimeController
|
class FlutterFormInputDateTimeController
|
||||||
implements FlutterFormInputController<String> {
|
implements FlutterFormInputController<String> {
|
||||||
FlutterFormInputDateTimeController({
|
FlutterFormInputDateTimeController({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
required this.dateTimeType,
|
||||||
|
required this.dateFormat,
|
||||||
this.mandatory = true,
|
this.mandatory = true,
|
||||||
this.value,
|
this.value,
|
||||||
this.checkPageTitle,
|
this.checkPageTitle,
|
||||||
this.checkPageDescription,
|
this.checkPageDescription,
|
||||||
this.initialDate,
|
this.initialDate,
|
||||||
this.initialDateTimeRange,
|
this.initialDateTimeRange,
|
||||||
required this.dateTimeType,
|
|
||||||
required this.dateFormat,
|
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
}) {
|
}) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
@ -118,13 +114,15 @@ class FlutterFormInputDateTimeController
|
||||||
void Function(String? value)? onSubmit;
|
void Function(String? value)? onSubmit;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onSaved(dynamic value) {
|
void onSaved(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(String? value,
|
String? onValidate(
|
||||||
String Function(String, {List<String>? params}) translator) {
|
String? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {
|
if (mandatory) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return translator('shell.form.error.empty');
|
return translator('shell.form.error.empty');
|
||||||
|
|
|
@ -3,31 +3,26 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
|
|
||||||
import '../../../../flutter_form.dart';
|
|
||||||
|
|
||||||
/// Input for an email used in a [FlutterForm].
|
/// Input for an email used in a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Standard controller is [FlutterFormInputEmailController].
|
/// Standard controller is [FlutterFormInputEmailController].
|
||||||
class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
|
class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
|
||||||
const FlutterFormInputEmail({
|
const FlutterFormInputEmail({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<String> controller,
|
super.key,
|
||||||
FocusNode? focusNode,
|
super.focusNode,
|
||||||
Widget? label,
|
super.label,
|
||||||
bool? enabled,
|
bool? enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
key: key,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
label: label,
|
|
||||||
enabled: enabled ?? true,
|
enabled: enabled ?? true,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
|
@ -42,13 +37,14 @@ class FlutterFormInputEmail extends FlutterFormInputWidget<String> {
|
||||||
onChanged: (value) => controller.onChanged?.call(value),
|
onChanged: (value) => controller.onChanged?.call(value),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
focusColor: Theme.of(context).primaryColor,
|
focusColor: Theme.of(context).primaryColor,
|
||||||
label: label ?? const Text("Email"),
|
label: label ?? const Text('Email'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for emails used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
/// Controller for emails used by a [FlutterFormInputWidget] used in
|
||||||
|
/// a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputEmail].
|
/// Mainly used by [FlutterFormInputEmail].
|
||||||
class FlutterFormInputEmailController
|
class FlutterFormInputEmailController
|
||||||
|
@ -85,21 +81,23 @@ class FlutterFormInputEmailController
|
||||||
void Function(String? value)? onSubmit;
|
void Function(String? value)? onSubmit;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onSaved(dynamic value) {
|
void onSaved(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(String? value,
|
String? onValidate(
|
||||||
String Function(String, {List<String>? params}) translator) {
|
String? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {
|
if (mandatory) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return translator('shell.form.error.empty');
|
return translator('shell.form.error.empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RegExp(
|
if (!RegExp(
|
||||||
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
|
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+",
|
||||||
.hasMatch(value)) {
|
).hasMatch(value)) {
|
||||||
return translator('shell.form.error.email.notValid');
|
return translator('shell.form.error.email.notValid');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
import '../../../../../flutter_form.dart';
|
|
||||||
|
|
||||||
/// Input for a number used in a [FlutterForm].
|
/// Input for a number used in a [FlutterForm].
|
||||||
///
|
///
|
||||||
|
@ -14,28 +14,26 @@ import '../../../../../flutter_form.dart';
|
||||||
/// Standard controller is [FlutterFormInputNumberPickerController].
|
/// Standard controller is [FlutterFormInputNumberPickerController].
|
||||||
class FlutterFormInputNumberPicker extends FlutterFormInputWidget<int> {
|
class FlutterFormInputNumberPicker extends FlutterFormInputWidget<int> {
|
||||||
const FlutterFormInputNumberPicker({
|
const FlutterFormInputNumberPicker({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<int> controller,
|
super.key,
|
||||||
Widget? label,
|
super.label,
|
||||||
FocusNode? focusNode,
|
|
||||||
this.minValue = 0,
|
this.minValue = 0,
|
||||||
this.maxValue = 100,
|
this.maxValue = 100,
|
||||||
}) : assert(minValue < maxValue),
|
}) : assert(minValue < maxValue, 'minValue must be less than maxValue');
|
||||||
super(key: key, controller: controller, label: label);
|
|
||||||
|
|
||||||
final int minValue;
|
final int minValue;
|
||||||
final int maxValue;
|
final int maxValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
return input.FlutterFormInputNumberPicker(
|
return input.FlutterFormInputNumberPicker(
|
||||||
minValue: minValue,
|
minValue: minValue,
|
||||||
maxValue: maxValue,
|
maxValue: maxValue,
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
onChanged: (value) => controller.onChanged?.call(value),
|
onChanged: (value) => controller.onChanged?.call(value),
|
||||||
initialValue: controller.value ?? minValue,
|
initialValue: controller.value ?? minValue,
|
||||||
|
@ -82,7 +80,9 @@ class FlutterFormInputNumberPickerController
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(
|
String? onValidate(
|
||||||
int? value, String Function(String, {List<String>? params}) translator) {
|
int? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {}
|
if (mandatory) {}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -3,24 +3,20 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
import '../../../../../flutter_form.dart';
|
|
||||||
|
|
||||||
/// Input for a password used in a [FlutterForm].
|
/// Input for a password used in a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Standard controller is [FlutterFormInputEmailController].
|
/// Standard controller is [FlutterFormInputEmailController].
|
||||||
class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
|
class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
|
||||||
const FlutterFormInputPassword({
|
const FlutterFormInputPassword({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<String> controller,
|
super.key,
|
||||||
FocusNode? focusNode,
|
super.focusNode,
|
||||||
Widget? label,
|
super.label,
|
||||||
bool? enabled,
|
bool? enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
key: key,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
label: label,
|
|
||||||
enabled: enabled ?? true,
|
enabled: enabled ?? true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -28,13 +24,13 @@ class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
return input.FlutterFormInputPassword(
|
return input.FlutterFormInputPassword(
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
initialValue: controller.value,
|
initialValue: controller.value,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
onChanged: (value) => controller.onChanged?.call(value),
|
onChanged: (value) => controller.onChanged?.call(value),
|
||||||
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
||||||
|
@ -42,7 +38,8 @@ class FlutterFormInputPassword extends FlutterFormInputWidget<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for passwords used by a [FlutterFormInputWidget] used in a [ShellFrom].
|
/// Controller for passwords used by a [FlutterFormInputWidget] used in a
|
||||||
|
/// [ShellFrom].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputPassword].
|
/// Mainly used by [FlutterFormInputPassword].
|
||||||
class FlutterFormInputPasswordController
|
class FlutterFormInputPasswordController
|
||||||
|
@ -79,13 +76,15 @@ class FlutterFormInputPasswordController
|
||||||
void Function(String? value)? onSubmit;
|
void Function(String? value)? onSubmit;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onSaved(dynamic value) {
|
void onSaved(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(String? value,
|
String? onValidate(
|
||||||
String Function(String, {List<String>? params}) translator) {
|
String? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {
|
if (mandatory) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return translator('Field can not be empty');
|
return translator('Field can not be empty');
|
||||||
|
|
|
@ -5,19 +5,18 @@
|
||||||
// ignore_for_file: overridden_fields
|
// ignore_for_file: overridden_fields
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
|
|
||||||
import '../../../../flutter_form.dart';
|
|
||||||
|
|
||||||
/// Input for plain text input used in a [FlutterForm].
|
/// Input for plain text input used in a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Standard controller is [FlutterFormInputPlainTextController].
|
/// Standard controller is [FlutterFormInputPlainTextController].
|
||||||
class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
||||||
const FlutterFormInputPlainText({
|
const FlutterFormInputPlainText({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<String> controller,
|
super.key,
|
||||||
FocusNode? focusNode,
|
super.focusNode,
|
||||||
Widget? label,
|
super.label,
|
||||||
this.decoration,
|
this.decoration,
|
||||||
this.textAlignVertical,
|
this.textAlignVertical,
|
||||||
this.expands = false,
|
this.expands = false,
|
||||||
|
@ -28,11 +27,7 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
this.style,
|
this.style,
|
||||||
this.textCapitalization = TextCapitalization.none,
|
this.textCapitalization = TextCapitalization.none,
|
||||||
}) : super(
|
});
|
||||||
key: key,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
label: label);
|
|
||||||
|
|
||||||
final InputDecoration? decoration;
|
final InputDecoration? decoration;
|
||||||
final TextAlignVertical? textAlignVertical;
|
final TextAlignVertical? textAlignVertical;
|
||||||
|
@ -48,13 +43,13 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
InputDecoration inputDecoration = decoration ??
|
var inputDecoration = decoration ??
|
||||||
InputDecoration(
|
InputDecoration(
|
||||||
label: label ?? const Text("Plain text"),
|
label: label ?? const Text('Plain text'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return input.FlutterFormInputPlainText(
|
return input.FlutterFormInputPlainText(
|
||||||
|
@ -63,7 +58,7 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
||||||
scrollPadding: scrollPadding ?? const EdgeInsets.all(20.0),
|
scrollPadding: scrollPadding ?? const EdgeInsets.all(20.0),
|
||||||
initialValue: controller.value,
|
initialValue: controller.value,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
onChanged: (value) => controller.onChanged?.call(value),
|
onChanged: (value) => controller.onChanged?.call(value),
|
||||||
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
onFieldSubmitted: (value) => controller.onSubmit?.call(value),
|
||||||
|
@ -87,15 +82,15 @@ class FlutterFormInputPlainText extends FlutterFormInputWidget<String> {
|
||||||
/// MaxCharacters can be set to set a maximum amount of characters.
|
/// MaxCharacters can be set to set a maximum amount of characters.
|
||||||
class FlutterFormInputMultiLine extends StatelessWidget {
|
class FlutterFormInputMultiLine extends StatelessWidget {
|
||||||
const FlutterFormInputMultiLine({
|
const FlutterFormInputMultiLine({
|
||||||
Key? key,
|
|
||||||
required this.controller,
|
required this.controller,
|
||||||
|
super.key,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
this.label,
|
this.label,
|
||||||
this.hint,
|
this.hint,
|
||||||
this.maxCharacters,
|
this.maxCharacters,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
this.textCapitalization = TextCapitalization.sentences,
|
this.textCapitalization = TextCapitalization.sentences,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final FlutterFormInputController<String> controller;
|
final FlutterFormInputController<String> controller;
|
||||||
final Widget? label;
|
final Widget? label;
|
||||||
|
@ -108,7 +103,7 @@ class FlutterFormInputMultiLine extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
return input.FlutterFormInputMultiLine(
|
return input.FlutterFormInputMultiLine(
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
|
@ -125,7 +120,8 @@ class FlutterFormInputMultiLine extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for plain text used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
/// Controller for plain text used by a [FlutterFormInputWidget] used in a
|
||||||
|
/// [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputPlainText].
|
/// Mainly used by [FlutterFormInputPlainText].
|
||||||
class FlutterFormInputPlainTextController
|
class FlutterFormInputPlainTextController
|
||||||
|
@ -167,8 +163,10 @@ class FlutterFormInputPlainTextController
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(String? value,
|
String? onValidate(
|
||||||
String Function(String, {List<String>? params}) translator) {
|
String? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {
|
if (mandatory) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return translator('Field can not be empty');
|
return translator('Field can not be empty');
|
||||||
|
|
|
@ -3,46 +3,42 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
|
|
||||||
import '../../../../../flutter_form.dart';
|
/// Input for a number value between two values via a slider. Used in a
|
||||||
|
/// [FlutterForm].
|
||||||
/// Input for a number value between two values via a slider. Used in a [FlutterForm].
|
|
||||||
///
|
///
|
||||||
/// Standard controller is [FlutterFormInputSliderController].
|
/// Standard controller is [FlutterFormInputSliderController].
|
||||||
class FlutterFormInputSlider extends FlutterFormInputWidget<double> {
|
class FlutterFormInputSlider extends FlutterFormInputWidget<double> {
|
||||||
const FlutterFormInputSlider({
|
const FlutterFormInputSlider({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<double> controller,
|
super.key,
|
||||||
FocusNode? focusNode,
|
super.focusNode,
|
||||||
Widget? label,
|
super.label,
|
||||||
this.minValue = 0,
|
this.minValue = 0,
|
||||||
this.maxValue = 100,
|
this.maxValue = 100,
|
||||||
}) : assert(minValue < maxValue),
|
}) : assert(minValue < maxValue, 'minValue must be less than maxValue');
|
||||||
super(
|
|
||||||
key: key,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
label: label);
|
|
||||||
|
|
||||||
final int minValue;
|
final int minValue;
|
||||||
final int maxValue;
|
final int maxValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
return input.FlutterFormInputSlider(
|
return input.FlutterFormInputSlider(
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for slider used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
/// Controller for slider used by a [FlutterFormInputWidget] used in a
|
||||||
|
/// [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputSlider].
|
/// Mainly used by [FlutterFormInputSlider].
|
||||||
class FlutterFormInputSliderController
|
class FlutterFormInputSliderController
|
||||||
|
@ -83,8 +79,10 @@ class FlutterFormInputSliderController
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(double? value,
|
String? onValidate(
|
||||||
String Function(String, {List<String>? params}) translator) {
|
double? value,
|
||||||
|
String Function(String, {List<String>? params}) translator,
|
||||||
|
) {
|
||||||
if (mandatory) {}
|
if (mandatory) {}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// ignore_for_file: avoid_positional_boolean_parameters
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_form_wizard/flutter_form.dart';
|
import 'package:flutter_form_wizard/flutter_form.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
|
@ -11,25 +13,21 @@ import 'package:flutter_input_library/flutter_input_library.dart' as input;
|
||||||
/// Standard controller is [FlutterFormInputSwitchController].
|
/// Standard controller is [FlutterFormInputSwitchController].
|
||||||
class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
|
class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
|
||||||
const FlutterFormInputSwitch({
|
const FlutterFormInputSwitch({
|
||||||
Key? key,
|
required super.controller,
|
||||||
required FlutterFormInputController<bool> controller,
|
super.key,
|
||||||
FocusNode? focusNode,
|
super.focusNode,
|
||||||
Widget? label,
|
super.label,
|
||||||
}) : super(
|
});
|
||||||
key: key,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
label: label);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String Function(String, {List<String>? params}) _ = getTranslator(context);
|
var _ = getTranslator(context);
|
||||||
|
|
||||||
super.registerController(context);
|
super.registerController(context);
|
||||||
|
|
||||||
return input.FlutterFormInputBool(
|
return input.FlutterFormInputBool(
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
onSaved: (value) => controller.onSaved(value),
|
onSaved: controller.onSaved,
|
||||||
onChanged: controller.onChanged,
|
onChanged: controller.onChanged,
|
||||||
validator: (value) => controller.onValidate(value, _),
|
validator: (value) => controller.onValidate(value, _),
|
||||||
initialValue: controller.value ?? false,
|
initialValue: controller.value ?? false,
|
||||||
|
@ -38,7 +36,8 @@ class FlutterFormInputSwitch extends FlutterFormInputWidget<bool> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controller for the switch used by a [FlutterFormInputWidget] used in a [FlutterForm].
|
/// Controller for the switch used by a [FlutterFormInputWidget] used in a
|
||||||
|
/// [FlutterForm].
|
||||||
///
|
///
|
||||||
/// Mainly used by [FlutterFormInputSwitch].
|
/// Mainly used by [FlutterFormInputSwitch].
|
||||||
class FlutterFormInputSwitchController
|
class FlutterFormInputSwitchController
|
||||||
|
@ -80,7 +79,8 @@ class FlutterFormInputSwitchController
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? onValidate(
|
String? onValidate(
|
||||||
bool? value, String Function(String, {List<String>? params}) translator) {
|
bool? value,
|
||||||
return null;
|
String Function(String, {List<String>? params}) translator,
|
||||||
}
|
) =>
|
||||||
|
null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
export 'input_carousel/input_carousel.dart';
|
export 'input_carousel/input_carousel.dart';
|
||||||
|
export 'input_date_picker/input_date_picker.dart';
|
||||||
export 'input_email.dart';
|
export 'input_email.dart';
|
||||||
export 'input_number_picker/input_number_picker.dart';
|
export 'input_number_picker/input_number_picker.dart';
|
||||||
export 'input_password/input_password.dart';
|
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';
|
|
||||||
|
|
|
@ -2,27 +2,45 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// ignore_for_file: avoid_positional_boolean_parameters
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// The options used to set parameters to a [FlutterForm].
|
/// The options used to set parameters to a [FlutterForm].
|
||||||
///
|
///
|
||||||
/// The pages determine what pages the pageview will contain via a [List] of [FlutterFormPage]s.
|
/// The pages determine what pages the pageview will contain via a [List] of
|
||||||
|
/// [FlutterFormPage]s.
|
||||||
///
|
///
|
||||||
/// Using a checkpage gives the ability for the user to check all input values before commiting by [CheckPage].
|
/// Using a checkpage gives the ability for the user to check all input values
|
||||||
|
/// before commiting by [CheckPage].
|
||||||
/// If [checkPage] is null no check page will be shown.
|
/// If [checkPage] is null no check page will be shown.
|
||||||
///
|
///
|
||||||
/// [nextButton] and [backButton] are both a way to give controls to user.
|
/// [nextButton] and [backButton] are both a way to give controls to user.
|
||||||
/// Both are just plain widgets used in a [Stack]. So the widgets can be aligned where ever.
|
/// Both are just plain widgets used in a [Stack]. So the widgets can be
|
||||||
|
/// aligned where ever.
|
||||||
/// The formcontroller of [FlutterForm] should be used to give control to the widgets/buttons.
|
/// The formcontroller of [FlutterForm] should be used to give control to the widgets/buttons.
|
||||||
///
|
///
|
||||||
/// [onFinished] and [onNext] are both callbacks which give the users results.
|
/// [onFinished] and [onNext] are both callbacks which give the users results.
|
||||||
/// [onNext] is called when the user goes to the next page.
|
/// [onNext] is called when the user goes to the next page.
|
||||||
/// [onFinished] is called when the form is finished. When checkpage is set [onFinished] is called when the checkpage is finished.
|
/// [onFinished] is called when the form is finished. When checkpage is set
|
||||||
|
/// [onFinished] is called when the checkpage is finished.
|
||||||
///
|
///
|
||||||
/// [scrollDirection] can be set to change the Axis on which the pageview slides. Defaults to horizontal.
|
/// [scrollDirection] can be set to change the Axis on which the pageview
|
||||||
|
/// slides. Defaults to horizontal.
|
||||||
///
|
///
|
||||||
/// [scrollPhysics] can be set to set the scroll phyisics of the scroll views in each page. Default to [ClampingScrollPhysics].
|
/// [scrollPhysics] can be set to set the scroll phyisics of the scroll views
|
||||||
|
/// in each page. Default to [ClampingScrollPhysics].
|
||||||
class FlutterFormOptions {
|
class FlutterFormOptions {
|
||||||
|
const FlutterFormOptions({
|
||||||
|
required this.pages,
|
||||||
|
required this.onFinished,
|
||||||
|
required this.onNext,
|
||||||
|
this.checkPage,
|
||||||
|
this.nextButton,
|
||||||
|
this.backButton,
|
||||||
|
this.scrollDirection = Axis.horizontal,
|
||||||
|
this.scrollPhysics,
|
||||||
|
});
|
||||||
final List<FlutterFormPage> pages;
|
final List<FlutterFormPage> pages;
|
||||||
|
|
||||||
final CheckPage? checkPage;
|
final CheckPage? checkPage;
|
||||||
|
@ -33,30 +51,19 @@ class FlutterFormOptions {
|
||||||
final void Function(int pageNumber, Map<String, dynamic>) onNext;
|
final void Function(int pageNumber, Map<String, dynamic>) onNext;
|
||||||
final Axis scrollDirection;
|
final Axis scrollDirection;
|
||||||
final ScrollPhysics? scrollPhysics;
|
final ScrollPhysics? scrollPhysics;
|
||||||
|
|
||||||
const FlutterFormOptions({
|
|
||||||
required this.pages,
|
|
||||||
this.checkPage,
|
|
||||||
this.nextButton,
|
|
||||||
this.backButton,
|
|
||||||
required this.onFinished,
|
|
||||||
required this.onNext,
|
|
||||||
this.scrollDirection = Axis.horizontal,
|
|
||||||
this.scrollPhysics,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The defines every page in a [FlutterForm].
|
/// The defines every page in a [FlutterForm].
|
||||||
class FlutterFormPage {
|
class FlutterFormPage {
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
FlutterFormPage({
|
FlutterFormPage({
|
||||||
required this.child,
|
required this.child,
|
||||||
});
|
});
|
||||||
|
final Widget child;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [CheckPage] is used to set a check page at the end of a [FlutterForm].
|
/// [CheckPage] is used to set a check page at the end of a [FlutterForm].
|
||||||
/// A [CheckPage] is a page where the user can check all input values before commiting.
|
/// A [CheckPage] is a page where the user can check all input values before
|
||||||
|
/// commiting.
|
||||||
///
|
///
|
||||||
/// [title] is the widget shown at the top of the page.
|
/// [title] is the widget shown at the top of the page.
|
||||||
///
|
///
|
||||||
|
@ -64,22 +71,28 @@ class FlutterFormPage {
|
||||||
///
|
///
|
||||||
/// [inputCheckWidget] determines how every input is represented on the page.
|
/// [inputCheckWidget] determines how every input is represented on the page.
|
||||||
/// [title] is the value given in the input.
|
/// [title] is the value given in the input.
|
||||||
/// This input can be modified by setting the [checkPageTitle] of that input controller.
|
/// This input can be modified by setting the [checkPageTitle] of that input
|
||||||
|
/// controller.
|
||||||
///
|
///
|
||||||
/// Same for the [description] but if the description is not set in the input controller no description will be given.
|
/// Same for the [description] but if the description is not set in the input
|
||||||
|
/// controller no description will be given.
|
||||||
///
|
///
|
||||||
/// [onPressed] can be set so that when the user triggers it the user will be sent back to the page including the input.
|
/// [onPressed] can be set so that when the user triggers it the user will be
|
||||||
/// Here the user can modify the input and save it. Afterwards the user will be sent back to the check page.
|
/// sent back to the page including the input.
|
||||||
|
/// Here the user can modify the input and save it. Afterwards the user will be
|
||||||
|
/// sent back to the check page.
|
||||||
class CheckPage {
|
class CheckPage {
|
||||||
final Widget? title;
|
|
||||||
final MainAxisAlignment mainAxisAlignment;
|
|
||||||
final Widget Function(
|
|
||||||
String id, String title, String? description, Function onPressed)?
|
|
||||||
inputCheckWidget;
|
|
||||||
|
|
||||||
const CheckPage({
|
const CheckPage({
|
||||||
this.title,
|
this.title,
|
||||||
this.inputCheckWidget,
|
this.inputCheckWidget,
|
||||||
this.mainAxisAlignment = MainAxisAlignment.start,
|
this.mainAxisAlignment = MainAxisAlignment.start,
|
||||||
});
|
});
|
||||||
|
final Widget? title;
|
||||||
|
final MainAxisAlignment mainAxisAlignment;
|
||||||
|
final Widget Function(
|
||||||
|
String id,
|
||||||
|
String title,
|
||||||
|
String? description,
|
||||||
|
Function onPressed,
|
||||||
|
)? inputCheckWidget;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,11 @@ typedef Translator = String Function(
|
||||||
|
|
||||||
class ShellTranslationService implements TranslationService {
|
class ShellTranslationService implements TranslationService {
|
||||||
@override
|
@override
|
||||||
String number(double value) {
|
String number(double value) => value.toStringAsFixed(2);
|
||||||
return value.toStringAsFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String translate(BuildContext context, String key, {List<String>? params}) {
|
String translate(BuildContext context, String key, {List<String>? params}) =>
|
||||||
return key;
|
key;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Translator getTranslator(BuildContext context) {
|
Translator getTranslator(BuildContext context) {
|
||||||
|
@ -39,15 +36,13 @@ Translator getTranslator(BuildContext context) {
|
||||||
return (
|
return (
|
||||||
String key, {
|
String key, {
|
||||||
List<String>? params,
|
List<String>? params,
|
||||||
}) {
|
}) =>
|
||||||
return translator(context, key, params: params);
|
translator(context, key, params: params);
|
||||||
};
|
} on Exception catch (_) {
|
||||||
} catch (e) {
|
|
||||||
return (
|
return (
|
||||||
String key, {
|
String key, {
|
||||||
List<String>? params,
|
List<String>? params,
|
||||||
}) {
|
}) =>
|
||||||
return key;
|
key;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_form_wizard
|
name: flutter_form_wizard
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 6.2.2
|
version: 6.2.3
|
||||||
homepage: https://github.com/Iconica-Development/flutter_form_wizard
|
homepage: https://github.com/Iconica-Development/flutter_form_wizard
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
@ -23,7 +23,10 @@ dependencies:
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
flutter_iconica_analysis:
|
||||||
|
git:
|
||||||
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
ref: 6.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Normal walk through without check page', (tester) async {
|
testWidgets('Normal walk through without check page', (tester) async {
|
||||||
FlutterFormController formController = FlutterFormController();
|
var formController = FlutterFormController();
|
||||||
|
|
||||||
var testField1Controller = FlutterFormInputPlainTextController(
|
var testField1Controller = FlutterFormInputPlainTextController(
|
||||||
id: 'Field1',
|
id: 'Field1',
|
||||||
|
@ -28,21 +28,21 @@ void main() {
|
||||||
home: Material(
|
home: Material(
|
||||||
child: FlutterForm(
|
child: FlutterForm(
|
||||||
options: FlutterFormOptions(
|
options: FlutterFormOptions(
|
||||||
nextButton: (pageNumber, checkingPages) {
|
nextButton: (pageNumber, checkingPages) => Align(
|
||||||
return Align(
|
alignment: Alignment.bottomCenter,
|
||||||
alignment: Alignment.bottomCenter,
|
child: ElevatedButton(
|
||||||
child: ElevatedButton(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
await formController.autoNextStep();
|
||||||
await formController.autoNextStep();
|
},
|
||||||
},
|
child: Text(
|
||||||
child: Text(pageNumber == 0
|
pageNumber == 0
|
||||||
? 'next1'
|
? 'next1'
|
||||||
: pageNumber == 1
|
: pageNumber == 1
|
||||||
? 'next2'
|
? 'next2'
|
||||||
: 'finish'),
|
: 'finish',
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
onFinished: (Map<int, Map<String, dynamic>> results) {
|
onFinished: (Map<int, Map<String, dynamic>> results) {
|
||||||
onFinishResults = results;
|
onFinishResults = results;
|
||||||
},
|
},
|
||||||
|
@ -76,7 +76,9 @@ void main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.widgetWithText(TextFormField, 'Field1Label'), 'Field1Input');
|
find.widgetWithText(TextFormField, 'Field1Label'),
|
||||||
|
'Field1Input',
|
||||||
|
);
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, 'next1'));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'next1'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
@ -84,21 +86,26 @@ void main() {
|
||||||
expect({'Field1': 'Field1Input'}, onNextResults);
|
expect({'Field1': 'Field1Input'}, onNextResults);
|
||||||
|
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.widgetWithText(TextFormField, 'Field2Label'), 'Field2Input');
|
find.widgetWithText(TextFormField, 'Field2Label'),
|
||||||
|
'Field2Input',
|
||||||
|
);
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, 'next2'));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'next2'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(1, onNextPageNumber);
|
expect(1, onNextPageNumber);
|
||||||
expect({'Field2': 'Field2Input'}, onNextResults);
|
expect({'Field2': 'Field2Input'}, onNextResults);
|
||||||
|
|
||||||
expect({
|
expect(
|
||||||
0: {'Field1': 'Field1Input'},
|
{
|
||||||
1: {'Field2': 'Field2Input'}
|
0: {'Field1': 'Field1Input'},
|
||||||
}, onFinishResults);
|
1: {'Field2': 'Field2Input'},
|
||||||
|
},
|
||||||
|
onFinishResults,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Normal walk through with check page', (tester) async {
|
testWidgets('Normal walk through with check page', (tester) async {
|
||||||
FlutterFormController formController = FlutterFormController();
|
var formController = FlutterFormController();
|
||||||
|
|
||||||
var testField1Controller = FlutterFormInputPlainTextController(
|
var testField1Controller = FlutterFormInputPlainTextController(
|
||||||
id: 'Field1',
|
id: 'Field1',
|
||||||
|
@ -119,21 +126,21 @@ void main() {
|
||||||
child: FlutterForm(
|
child: FlutterForm(
|
||||||
options: FlutterFormOptions(
|
options: FlutterFormOptions(
|
||||||
checkPage: const CheckPage(),
|
checkPage: const CheckPage(),
|
||||||
nextButton: (pageNumber, checkingPages) {
|
nextButton: (pageNumber, checkingPages) => Align(
|
||||||
return Align(
|
alignment: Alignment.bottomCenter,
|
||||||
alignment: Alignment.bottomCenter,
|
child: ElevatedButton(
|
||||||
child: ElevatedButton(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
await formController.autoNextStep();
|
||||||
await formController.autoNextStep();
|
},
|
||||||
},
|
child: Text(
|
||||||
child: Text(pageNumber == 0
|
pageNumber == 0
|
||||||
? 'next1'
|
? 'next1'
|
||||||
: pageNumber == 1
|
: pageNumber == 1
|
||||||
? 'next2'
|
? 'next2'
|
||||||
: 'finish'),
|
: 'finish',
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
onFinished: (Map<int, Map<String, dynamic>> results) {
|
onFinished: (Map<int, Map<String, dynamic>> results) {
|
||||||
onFinishResults = results;
|
onFinishResults = results;
|
||||||
},
|
},
|
||||||
|
@ -167,7 +174,9 @@ void main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.widgetWithText(TextFormField, 'Field1Label'), 'Field1Input');
|
find.widgetWithText(TextFormField, 'Field1Label'),
|
||||||
|
'Field1Input',
|
||||||
|
);
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, 'next1'));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'next1'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
@ -175,7 +184,9 @@ void main() {
|
||||||
expect({'Field1': 'Field1Input'}, onNextResults);
|
expect({'Field1': 'Field1Input'}, onNextResults);
|
||||||
|
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.widgetWithText(TextFormField, 'Field2Label'), 'Field2Input');
|
find.widgetWithText(TextFormField, 'Field2Label'),
|
||||||
|
'Field2Input',
|
||||||
|
);
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, 'next2'));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'next2'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
@ -186,24 +197,29 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.widgetWithText(TextFormField, 'Field1Label'), 'Field1Input2');
|
find.widgetWithText(TextFormField, 'Field1Label'),
|
||||||
|
'Field1Input2',
|
||||||
|
);
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, 'next1'));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'next1'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(0, onNextPageNumber);
|
expect(0, onNextPageNumber);
|
||||||
expect({'Field1': 'Field1Input2'}, onNextResults);
|
expect({'Field1': 'Field1Input2'}, onNextResults);
|
||||||
|
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, "finish"));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'finish'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect({
|
expect(
|
||||||
0: {'Field1': 'Field1Input2'},
|
{
|
||||||
1: {'Field2': 'Field2Input'}
|
0: {'Field1': 'Field1Input2'},
|
||||||
}, onFinishResults);
|
1: {'Field2': 'Field2Input'},
|
||||||
|
},
|
||||||
|
onFinishResults,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Wrong input with mandatory validator', (tester) async {
|
testWidgets('Wrong input with mandatory validator', (tester) async {
|
||||||
FlutterFormController formController = FlutterFormController();
|
var formController = FlutterFormController();
|
||||||
|
|
||||||
var testField1Controller = FlutterFormInputPlainTextController(
|
var testField1Controller = FlutterFormInputPlainTextController(
|
||||||
id: 'Field1',
|
id: 'Field1',
|
||||||
|
@ -220,17 +236,15 @@ void main() {
|
||||||
home: Material(
|
home: Material(
|
||||||
child: FlutterForm(
|
child: FlutterForm(
|
||||||
options: FlutterFormOptions(
|
options: FlutterFormOptions(
|
||||||
nextButton: (pageNumber, checkingPages) {
|
nextButton: (pageNumber, checkingPages) => Align(
|
||||||
return Align(
|
alignment: Alignment.bottomCenter,
|
||||||
alignment: Alignment.bottomCenter,
|
child: ElevatedButton(
|
||||||
child: ElevatedButton(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
await formController.autoNextStep();
|
||||||
await formController.autoNextStep();
|
},
|
||||||
},
|
child: const Text('finish'),
|
||||||
child: const Text('finish'),
|
),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
onFinished: (Map<int, Map<String, dynamic>> results) {
|
onFinished: (Map<int, Map<String, dynamic>> results) {
|
||||||
// print('finished results: $results');
|
// print('finished results: $results');
|
||||||
onFinishResults = results;
|
onFinishResults = results;
|
||||||
|
@ -263,20 +277,25 @@ void main() {
|
||||||
expect(null, onNextPageNumber);
|
expect(null, onNextPageNumber);
|
||||||
expect(null, onNextResults);
|
expect(null, onNextResults);
|
||||||
|
|
||||||
final errorMessageFinder = find.text('Field can not be empty');
|
var errorMessageFinder = find.text('Field can not be empty');
|
||||||
|
|
||||||
expect(errorMessageFinder, findsOneWidget);
|
expect(errorMessageFinder, findsOneWidget);
|
||||||
|
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.widgetWithText(TextFormField, 'Field1Label'), 'Field1Input');
|
find.widgetWithText(TextFormField, 'Field1Label'),
|
||||||
|
'Field1Input',
|
||||||
|
);
|
||||||
await tester.tap(find.widgetWithText(ElevatedButton, 'finish'));
|
await tester.tap(find.widgetWithText(ElevatedButton, 'finish'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(0, onNextPageNumber);
|
expect(0, onNextPageNumber);
|
||||||
expect({'Field1': 'Field1Input'}, onNextResults);
|
expect({'Field1': 'Field1Input'}, onNextResults);
|
||||||
|
|
||||||
expect({
|
expect(
|
||||||
0: {'Field1': 'Field1Input'},
|
{
|
||||||
}, onFinishResults);
|
0: {'Field1': 'Field1Input'},
|
||||||
|
},
|
||||||
|
onFinishResults,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue