Skip to content

Commit 7f0c09b

Browse files
Merge pull request #129 from ArturAssisComp/main
Implement the API modifications
2 parents 362dd46 + 1834d8e commit 7f0c09b

File tree

129 files changed

+15627
-112
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+15627
-112
lines changed

.gitignore

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ build/
3333
pubspec.lock
3434

3535
# Android related
36-
**/android/**/gradle-wrapper.jar
37-
**/android/.gradle
38-
**/android/captures/
39-
**/android/gradlew
40-
**/android/gradlew.bat
41-
**/android/local.properties
42-
**/android/**/GeneratedPluginRegistrant.java
36+
example/android_backup/**/gradle-wrapper.jar
37+
example/android_backup/.gradle
38+
example/android_backup/captures/
39+
example/android_backup/gradlew
40+
example/android_backup/gradlew.bat
41+
example/android_backup/local.properties
42+
example/android_backup/**/GeneratedPluginRegistrant.java
4343

4444
# iOS/XCode related
4545
**/ios/**/*.mode1v3

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,37 @@ Take a look at [our fantastic ecosystem](https://github.com/flutter-form-builder
418418
## Thanks to
419419

420420
[All contributors](https://github.com/flutter-form-builder-ecosystem/form_builder_validators/graphs/contributors)
421+
422+
423+
# API changes draft
424+
During the process of exploration of new possibilities for the new API, I realized that there are
425+
basically three layers of validators: required layer, type layer and the specialized layer. Instead of
426+
repeating the computations for required and type layer for each validator composition, it is possible
427+
to decouple them, avoiding this redundancy and taking benefits from the Dart compiler.
428+
429+
During the exploration, I implemented some elementary validators that would make it possible, by
430+
composition, to create more sophisticated validators. The recipe is simple, start with a (not)required
431+
validator, add a type validator, and then chain as many specialized validators as you want.
432+
433+
```dart
434+
// In this example, we build a validator composing a required, with a numeric and then a max.
435+
// The logic result is: required && numeric && max(70)
436+
437+
final validator = ValidatorBuilder.required(and: <Validator<Object, num>>[
438+
ValidatorBuilder.numeric(
439+
errorText: 'La edad debe ser numérica.',
440+
and: <BaseElementaryValidator<num, dynamic>>[
441+
ValidatorBuilder.max(70),
442+
])
443+
]).validate;
444+
```
445+
446+
I needed to change a little bit the approach. Instead of composing directly the validators as
447+
FormFieldValidator's, one level of indirection was necessary, using a ValidatorBuilder instead.
448+
Thus, we first build the validator and then create the validation method calling validate.
449+
450+
I implemented some examples that are related to some examples from example/main.dart. The new
451+
API examples are implemented in example/api_refactoring_main.dart. I recorded a video showing the
452+
execution of the examples and explaining the new api ideas.
453+
454+
Please, give me the necessary feedback for me to continue the work.

example/.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ app.*.symbols
4040
app.*.map.json
4141

4242
# Android Studio will place build artifacts here
43-
/android/app/debug
44-
/android/app/profile
45-
/android/app/release
43+
/android_backup/app/debug
44+
/android_backup/app/profile
45+
/android_backup/app/release

example/.metadata

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This file should be version controlled and should not be manually edited.
55

66
version:
7-
revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1"
7+
revision: "2663184aa79047d0a33a14a3b607954f8fdd8730"
88
channel: "stable"
99

1010
project_type: app
@@ -13,23 +13,26 @@ project_type: app
1313
migration:
1414
platforms:
1515
- platform: root
16-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
17-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
16+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
17+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
1818
- platform: android
19-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
20-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
19+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
20+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
2121
- platform: ios
22-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
23-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
22+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
23+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
24+
- platform: linux
25+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
26+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
2427
- platform: macos
25-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
26-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
28+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
29+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
2730
- platform: web
28-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
29-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
31+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
32+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
3033
- platform: windows
31-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
32-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
34+
create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
35+
base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
3336

3437
# User provided section
3538

example/android/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
33
zipStoreBase=GRADLE_USER_HOME
44
zipStorePath=wrapper/dists
5-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
5+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip

example/lib/basic_examples.dart

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:form_builder_validators/form_builder_validators.dart'
3+
show Validators;
4+
5+
/// Basic examples involving only one validator per example
6+
class BasicExamplesPage extends StatelessWidget {
7+
/// Constructs a new instance of the [BasicExamplesPage] class.
8+
const BasicExamplesPage({super.key});
9+
10+
@override
11+
Widget build(BuildContext context) {
12+
return Scaffold(
13+
appBar: AppBar(
14+
title: const Text('Basic Examples (one validator per example)')),
15+
body: Padding(
16+
padding: const EdgeInsets.all(8),
17+
child: SingleChildScrollView(
18+
child: Column(
19+
children: <Widget>[
20+
// Core validators
21+
Text(
22+
'Core Validators',
23+
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24),
24+
),
25+
Align(
26+
alignment: Alignment.centerLeft,
27+
child: Text(
28+
'Equality Validators',
29+
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
30+
),
31+
),
32+
TextFormField(
33+
decoration: const InputDecoration(
34+
labelText:
35+
'Type "I want to delete" to confirm the action.'),
36+
autovalidateMode: AutovalidateMode.onUserInteraction,
37+
validator: Validators.isEqual('I want to delete'),
38+
),
39+
TextFormField(
40+
decoration: const InputDecoration(
41+
labelText: 'Username (should not be "RESERVED")'),
42+
autovalidateMode: AutovalidateMode.onUserInteraction,
43+
validator: Validators.isNotEqual('RESERVED'),
44+
),
45+
Align(
46+
alignment: Alignment.centerLeft,
47+
child: Text(
48+
'Required Error Message',
49+
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
50+
),
51+
),
52+
TextFormField(
53+
decoration:
54+
const InputDecoration(labelText: 'Input must not be null'),
55+
autovalidateMode: AutovalidateMode.onUserInteraction,
56+
validator: (String? input) {
57+
final String? isRequiredMsg = Validators.isRequired()(input);
58+
return isRequiredMsg
59+
?.toUpperCase()
60+
.replaceFirst('OVERRIDE: ', '');
61+
},
62+
),
63+
],
64+
),
65+
),
66+
),
67+
);
68+
}
69+
}

0 commit comments

Comments
 (0)