Skip to content

Commit

Permalink
feat(validator): allow to control & customize validation
Browse files Browse the repository at this point in the history
* add PhoneFormField "validator" property
* [BC] remove PhoneFormField "errorText" & "phoneNumberType"
* [BC] remove BasePhoneFormField "errorText"
* add PhoneValidator class with static methods to customize how phonenumber is validated and the related error messages
* add defaults translations strings for supported locales
* add tests
* update README
* update CHANGELOG
* [example] refactor code according to above change
* [example] add required option
  • Loading branch information
emri99 committed Sep 20, 2021
1 parent 432fcfe commit 8d1df08
Show file tree
Hide file tree
Showing 32 changed files with 1,122 additions and 438 deletions.
190 changes: 98 additions & 92 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,98 @@
## [3.0.1] -
- added DraggableModalBottomSheet
- fix phone number type
- fix onChanged & onSaved
- fix late initialization error when no country was selected in bottom sheet selector

## [3.0.0] - 27 / 08 / 2021
- removed deprecated selector config
- added controllers to control the value
- added support for copy pasting

## [2.0.0] - 16 / 08 / 2021

- deprecating SelectorConfig in favor of CountrySelectorNavigator
- added unit tests
- fixes for auto fill and copy paste

## [1.2.0] - 25 / 05 / 2021
* Minor release introducing SelectorConfig.
* Fix problems with input focussing in cover sheet.

```
// cover sheet
PhoneFormField(
// ...
selectorConfig: SelectorConfigCoverSheet()
)
// dialog
PhoneFormField(
// ...
selectorConfig: SelectorConfigBottomSheet()
)
// bottom sheet
PhoneFormField(
// ...
selectorConfig: SelectorConfigBottomSheet(null)
)
```

## [1.1.3] - 25 / 05 / 2021
* fix initial value not setting up correctly
* Added different types of Country selector display: SelectorDisplay.coversBody, SelectorDisplay.coversLower. The old value is coversLower and the new default value is coversBody.

## [1.1.2] - 20 / 05 / 2021
* minor changelog fix.

## [1.1.1] - 20 / 05 / 2021
* Added key to exported widgets.

## [1.1.0] - 19 / 05 / 2021
* [Breaking] : some classes from the package phone_numbers_parser aren't exported anymore. Mostly classes that are not intended to be used with this package.
* Added example for widgets FlagDialCodeChip and CountrySelector
* Added default values for FlagDialCodeChip and removed some unused values.

## [1.0.2] - 23 / 04 / 2021
* Upped dependency phone_numbers_parser to 0.1.3
* Added phoneNumberType input to validate against specific types (mobile, fixed line)

## [1.0.1] - 23 / 04 / 2021
* Fixed validity issue (issue #1)
* Allow country to be searched by dial code (issue #2)
* Sort country search results to have more meaningful results at the top
* Upped dependency phone_numbers_parser to 0.1.0

## [1.0.0] - 21 / 04 / 2021

* Reworked internal so the PhoneFormField behaves exactly like a TextFormField

## [0.0.6] - 15 / 04 / 2021

* InputDecoration renamed to decoration to match formField

## [0.0.5] - 15 / 04 / 2021

* Match cursor color with border color

## [0.0.4] - 13 / 04 / 2021

* Default font size 14

## [0.0.3] - 13 / 04 / 2021

* Breaking: inputBorder parameter replaced by inputDecoration for more maneability

## [0.0.2] - 12 / 04 / 2021

* Fix unresponsive onSave


## [0.0.1] - 12 / 04 / 2021

* initial release
## [4.0.0] -
- Add PhoneFormField `validator` property
- **[BREAKING CHANGE]** Remove `PhoneFormField` properties `errorText` & `phoneNumberType`. Define `validator` property instead with `PhoneValidator.invalid*`
- **[BREAKING CHANGE]** Remove `BasePhoneFormField` property `errorText`. Define error message via `validator` property as usual
- Add PhoneValidator class to easily customize validation and defaults localization error messagees

## [3.0.1] -
- added DraggableModalBottomSheet
- fix phone number type
- fix onChanged & onSaved
- fix late initialization error when no country was selected in bottom sheet selector

## [3.0.0] - 27 / 08 / 2021
- removed deprecated selector config
- added controllers to control the value
- added support for copy pasting

## [2.0.0] - 16 / 08 / 2021

- deprecating SelectorConfig in favor of CountrySelectorNavigator
- added unit tests
- fixes for auto fill and copy paste

## [1.2.0] - 25 / 05 / 2021
* Minor release introducing SelectorConfig.
* Fix problems with input focussing in cover sheet.

```
// cover sheet
PhoneFormField(
// ...
selectorConfig: SelectorConfigCoverSheet()
)
// dialog
PhoneFormField(
// ...
selectorConfig: SelectorConfigBottomSheet()
)
// bottom sheet
PhoneFormField(
// ...
selectorConfig: SelectorConfigBottomSheet(null)
)
```

## [1.1.3] - 25 / 05 / 2021
* fix initial value not setting up correctly
* Added different types of Country selector display: SelectorDisplay.coversBody, SelectorDisplay.coversLower. The old value is coversLower and the new default value is coversBody.

## [1.1.2] - 20 / 05 / 2021
* minor changelog fix.

## [1.1.1] - 20 / 05 / 2021
* Added key to exported widgets.

## [1.1.0] - 19 / 05 / 2021
* [Breaking] : some classes from the package phone_numbers_parser aren't exported anymore. Mostly classes that are not intended to be used with this package.
* Added example for widgets FlagDialCodeChip and CountrySelector
* Added default values for FlagDialCodeChip and removed some unused values.

## [1.0.2] - 23 / 04 / 2021
* Upped dependency phone_numbers_parser to 0.1.3
* Added phoneNumberType input to validate against specific types (mobile, fixed line)

## [1.0.1] - 23 / 04 / 2021
* Fixed validity issue (issue #1)
* Allow country to be searched by dial code (issue #2)
* Sort country search results to have more meaningful results at the top
* Upped dependency phone_numbers_parser to 0.1.0

## [1.0.0] - 21 / 04 / 2021

* Reworked internal so the PhoneFormField behaves exactly like a TextFormField

## [0.0.6] - 15 / 04 / 2021

* InputDecoration renamed to decoration to match formField

## [0.0.5] - 15 / 04 / 2021

* Match cursor color with border color

## [0.0.4] - 13 / 04 / 2021

* Default font size 14

## [0.0.3] - 13 / 04 / 2021

* Breaking: inputBorder parameter replaced by inputDecoration for more maneability

## [0.0.2] - 12 / 04 / 2021

* Fix unresponsive onSave


## [0.0.1] - 12 / 04 / 2021

* initial release
49 changes: 45 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Flutter phone input integrated with flutter internationalization

- Totally cross platform, this is a dart only package / dependencies
- Internationalization
- Phone number validation
- Phone number validation (built-in validators included for main use cases)
- Support autofill and copy paste
- Extends Flutter's FormField
- Uses dart phone_numbers_parser for parsing
Expand All @@ -28,21 +28,62 @@ PhoneFormField(
border: OutlineInputBorder(),
// ...
),
phoneNumberType: null, // can be PhoneNumberType.mobile or phoneNumberType.fixed or null for both validation
validator: PhoneValidator.compose([
// list of validators to use (see Built-in validators section below)
PhoneValidator.required(context, errorText: "You must enter a value"),
PhoneValidator.invalidMobile(context),
// ...
]),
selectorNavigator: const BottomSheetNavigator(), // default to bottom sheet but you can customize how the selector is shown by extending CountrySelectorNavigator
lightParser: false, // using true here reduce memory foot print but only use length to validate
),
```

## Built-in validators

* required : `PhoneValidator.required`
* invalid : `PhoneValidator.invalid` (default used when no validator supplied)
* invalid mobile number : `PhoneValidator.invalidMobile`
* invalid fixed line number : `PhoneValidator.invalidFixedLine`
* invalid type : `PhoneValidator.invalidType`
* invalid country : `PhoneValidator.invalidCountry`
* none : `PhoneValidator.none` (this can be used to disable default invalid validator)

### Validators details

* Each validator has an optional `errorText` property to override built-in translated text
* Validating phone number can use a lightweight version of the parser with `useLightParser` argument (uses only length to validate)
* Most of them have an optional `allowEmpty` (default is true) preventing to flag an empty field as invalid. Consider using a composed validator with a first `PhoneValidator.required` when a different text is needed for empty field.
* Built-in validators are related to `PhoneFormField`. For `BasePhoneFormField`, you have to defined your own validators.

### Composing validators

Validator can be a composed set of validators built-in or custom validator using `PhoneValidator.compose`, see usage section.

Note that when composing validators, the sorting is important as the error message displayed is the first validator failing.

```dart
PhoneFormField(
// ...
validator: PhoneValidator.compose([
// list of validators to use
PhoneValidator.required(context, errorText: "You must enter a value"),
PhoneValidator.invalidMobile(context),
// ...
]),
)
```


## Internationalization

Include the delegate

```dart
return MaterialApp(
localizationsDelegates: [
...GlobalMaterialLocalizations.delegates,
GlobalMaterialLocalizations.delegate,
PhoneFieldLocalization.delegate
],
supportedLocales: [
Expand All @@ -54,7 +95,7 @@ PhoneFormField(
],
```

Tnat's it.
That's it.


A bunch of languages are built-in:
Expand Down
43 changes: 31 additions & 12 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:example/widgets/app_drawer.dart';
import 'package:example/widgets/switch_el.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
Expand All @@ -11,13 +10,24 @@ void main() {
/// putting the widget at the top so it's easily findable in pub.dev example
Widget getPhoneField({
required BuildContext context,
required PhoneController controller,
required CountrySelectorNavigator selectorNavigator,
required bool withLabel,
required bool outlineBorder,
required bool required,
required bool mobileOnly,
required bool autovalidate,
}) {
List<PhoneNumberInputValidator> validators = [];
if (required) {
validators.add(PhoneValidator.required(context));
}
if (mobileOnly) {
validators.add(PhoneValidator.invalidMobile(context));
}
PhoneNumberInputValidator? validator =
validators.isNotEmpty ? PhoneValidator.compose(validators) : null;
return AutofillGroup(
child: PhoneFormField(
autofocus: true,
Expand All @@ -31,11 +41,10 @@ Widget getPhoneField({
),
enabled: true,
showFlagInInput: true,
phoneNumberType: mobileOnly ? PhoneNumberType.mobile : null,
validator: validator,
autovalidateMode: autovalidate
? AutovalidateMode.onUserInteraction
: AutovalidateMode.disabled,
errorText: 'Invalid phone',
onChanged: (p) => print('changed $p'),
),
);
Expand All @@ -46,7 +55,7 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
...GlobalMaterialLocalizations.delegates,
GlobalMaterialLocalizations.delegate,
PhoneFieldLocalization.delegate
],
supportedLocales: [
Expand Down Expand Up @@ -79,6 +88,7 @@ class _PhoneFormFieldScreenState extends State<PhoneFormFieldScreen> {
bool withLabel = true;
bool autovalidate = true;
bool mobileOnly = true;
bool required = false;
CountrySelectorNavigator selectorNavigator = const BottomSheetNavigator();

@override
Expand Down Expand Up @@ -131,6 +141,11 @@ class _PhoneFormFieldScreenState extends State<PhoneFormFieldScreen> {
onChanged: (v) => setState(() => withLabel = v),
title: 'Label',
),
SwitchEl(
value: required,
onChanged: (v) => setState(() => required = v),
title: 'Required',
),
SwitchEl(
value: mobileOnly,
onChanged: (v) => setState(() => mobileOnly = v),
Expand Down Expand Up @@ -177,14 +192,18 @@ class _PhoneFormFieldScreenState extends State<PhoneFormFieldScreen> {
// ],
// ),
// ),
getPhoneField(
controller: controller,
selectorNavigator: selectorNavigator,
withLabel: withLabel,
outlineBorder: outlineBorder,
mobileOnly: mobileOnly,
autovalidate: autovalidate,
),
Builder(builder: (context) {
return getPhoneField(
context: context,
controller: controller,
selectorNavigator: selectorNavigator,
withLabel: withLabel,
outlineBorder: outlineBorder,
required: required,
mobileOnly: mobileOnly,
autovalidate: autovalidate,
);
}),
SizedBox(
height: 40,
),
Expand Down
6 changes: 5 additions & 1 deletion lib/l10n/ar.arb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"@@locale": "ar",
"invalidPhoneNumber": "رقم الهاتف غير صحيح",
"invalidCountry": "دولة غير صحيح",
"invalidMobilePhoneNumber": "رقم الهاتف الخلوي غير صحيح",
"invalidFixedLinePhoneNumber": "رقم الهاتف الثابت غير صحيح",
"requiredPhoneNumber": "رقم الهاتف مطلوب",
"noResultMessage": "لا نتيجة",
"ad_": "أندورا",
"ae_": "الإمارات العربية المتحدة",
Expand Down Expand Up @@ -244,4 +248,4 @@
"za_": "جنوب أفريقيا",
"zm_": "زامبيا",
"zw_": "زيمبابوي"
}
}

0 comments on commit 8d1df08

Please sign in to comment.