Skip to content

Commit a175958

Browse files
fix: able to patch value
1 parent be94fa9 commit a175958

File tree

2 files changed

+148
-37
lines changed

2 files changed

+148
-37
lines changed

lib/src/form_builder_phone_field.dart

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,18 @@ class FormBuilderPhoneField extends FormBuilderField<String> {
128128

129129
/// Creates field for international phone number input.
130130
FormBuilderPhoneField({
131-
Key? key,
132-
//From Super
133-
required String name,
134-
FormFieldValidator<String>? validator,
135-
String? initialValue,
136-
InputDecoration decoration = const InputDecoration(),
137-
ValueChanged<String?>? onChanged,
138-
ValueTransformer<String?>? valueTransformer,
139-
bool enabled = true,
140-
FormFieldSetter<String>? onSaved,
141-
AutovalidateMode autovalidateMode = AutovalidateMode.disabled,
142-
VoidCallback? onReset,
143-
FocusNode? focusNode,
131+
super.key,
132+
required super.name,
133+
super.validator,
134+
super.initialValue,
135+
super.decoration,
136+
super.onChanged,
137+
super.valueTransformer,
138+
super.enabled,
139+
super.onSaved,
140+
AutovalidateMode super.autovalidateMode = AutovalidateMode.disabled,
141+
super.onReset,
142+
super.focusNode,
144143
this.obscureText = false,
145144
this.textCapitalization = TextCapitalization.none,
146145
this.scrollPadding = const EdgeInsets.all(20.0),
@@ -197,18 +196,6 @@ class FormBuilderPhoneField extends FormBuilderField<String> {
197196
this.searchEmptyView,
198197
}) : assert(initialValue == null || controller == null),
199198
super(
200-
key: key,
201-
initialValue: initialValue,
202-
name: name,
203-
validator: validator,
204-
valueTransformer: valueTransformer,
205-
onChanged: onChanged,
206-
autovalidateMode: autovalidateMode,
207-
onSaved: onSaved,
208-
enabled: enabled,
209-
onReset: onReset,
210-
decoration: decoration,
211-
focusNode: focusNode,
212199
builder: (FormFieldState<String?> field) {
213200
final state = field as _FormBuilderPhoneFieldState;
214201

@@ -262,8 +249,9 @@ class FormBuilderPhoneField extends FormBuilderField<String> {
262249
hintText: decoration.hintText,
263250
hintStyle: decoration.hintStyle,
264251
),
265-
onChanged: (_) {
266-
state.invokeChange();
252+
onChanged: (value) {
253+
// Use setValue instead didChange to avoid parseNumber
254+
state.setValue(value);
267255
},
268256
maxLines: 1,
269257
keyboardType: keyboardType,
@@ -331,7 +319,6 @@ class _FormBuilderPhoneFieldState
331319

332320
@override
333321
void dispose() {
334-
// Dispose the _effectiveController when initState created it
335322
if (null == widget.controller) {
336323
_effectiveController.dispose();
337324
}
@@ -347,25 +334,29 @@ class _FormBuilderPhoneFieldState
347334
_parsePhone();
348335
}
349336

350-
Future<void> _parsePhone() async {
351-
if (initialValue != null && initialValue!.isNotEmpty) {
337+
Future<void> _parsePhone({String? newPhone}) async {
338+
final phone = newPhone ?? initialValue ?? '';
339+
if (phone.isNotEmpty) {
352340
try {
353-
final parseResult = await PhoneNumberUtil().parse(initialValue!);
341+
final parseResult = await PhoneNumberUtil().parse(phone);
354342
setState(() {
355343
_selectedDialogCountry =
356344
CountryPickerUtils.getCountryByIsoCode(parseResult.regionCode);
357345
});
358346
_effectiveController.text = parseResult.nationalNumber;
359347
} catch (error) {
360-
_effectiveController.text = initialValue!.replaceFirst('+', '');
348+
if (phone.contains('+')) {
349+
_effectiveController.text = phone.replaceFirst('+', '');
350+
}
361351
debugPrint(error.toString());
362352
}
363353
}
364354
}
365355

366-
void invokeChange() {
367-
didChange(fullNumber);
368-
widget.onChanged?.call(fullNumber);
356+
@override
357+
void didChange(String? value) async {
358+
super.didChange(value);
359+
await _parsePhone(newPhone: value);
369360
}
370361

371362
void _openCupertinoCountryPicker() {
@@ -434,7 +425,7 @@ class _FormBuilderPhoneFieldState
434425
),
435426
onValuePicked: (Country country) {
436427
setState(() => _selectedDialogCountry = country);
437-
invokeChange();
428+
didChange(fullNumber);
438429
},
439430
itemFilter: widget.countryFilterByIsoCode != null
440431
? (c) => widget.countryFilterByIsoCode!.contains(c.isoCode)
Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,125 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_form_builder/flutter_form_builder.dart';
13
import 'package:flutter_test/flutter_test.dart';
24

5+
import 'package:form_builder_phone_field/form_builder_phone_field.dart';
6+
37
void main() {
4-
test('adds one to input values', () {});
8+
group('by FormFieldKey -', () {
9+
testWidgets('should reset value when call reset', (tester) async {
10+
final formFieldKey = GlobalKey<FormBuilderFieldState>();
11+
const fieldName = 'phone';
12+
final testWidget =
13+
FormBuilderPhoneField(name: fieldName, key: formFieldKey);
14+
const validPhone = '642337488';
15+
const validCodePhone = '+34';
16+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
17+
18+
formFieldKey.currentState?.setValue('$validCodePhone$validPhone');
19+
await tester.pumpAndSettle();
20+
formFieldKey.currentState?.reset();
21+
22+
expect(formFieldKey.currentState?.value, null);
23+
});
24+
testWidgets('should reset value to initial value when call reset',
25+
(tester) async {
26+
final formFieldKey = GlobalKey<FormBuilderFieldState>();
27+
const fieldName = 'phone';
28+
const initialValue = '12345';
29+
final testWidget = FormBuilderPhoneField(
30+
name: fieldName,
31+
key: formFieldKey,
32+
initialValue: initialValue,
33+
);
34+
const validPhone = '642337488';
35+
const validCodePhone = '+34';
36+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
37+
38+
formFieldKey.currentState?.setValue('$validCodePhone$validPhone');
39+
await tester.pumpAndSettle();
40+
formFieldKey.currentState?.reset();
41+
42+
expect(formFieldKey.currentState?.value, initialValue);
43+
});
44+
testWidgets('should update value when call set value', (tester) async {
45+
final formFieldKey = GlobalKey<FormBuilderFieldState>();
46+
const fieldName = 'phone';
47+
const validPhone = '691375833';
48+
const validCodePhone = '+34';
49+
final testWidget =
50+
FormBuilderPhoneField(name: fieldName, key: formFieldKey);
51+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
52+
53+
formFieldKey.currentState?.didChange('$validCodePhone$validPhone');
54+
await tester.pumpAndSettle();
55+
56+
expect(formFieldKey.currentState?.value, '$validCodePhone$validPhone');
57+
});
58+
});
59+
group('by FormKey -', () {
60+
testWidgets('should reset value when call reset', (tester) async {
61+
final formKey = GlobalKey<FormBuilderState>();
62+
const fieldName = 'phone';
63+
final testWidget = FormBuilderPhoneField(name: fieldName);
64+
await tester
65+
.pumpWidget(buildTestableFieldWidget(testWidget, formKey: formKey));
66+
67+
formKey.currentState?.patchValue({fieldName: '+34649294281'});
68+
await tester.pumpAndSettle();
69+
formKey.currentState?.reset();
70+
71+
expect(formKey.currentState?.instantValue, {fieldName: null});
72+
});
73+
testWidgets('should reset to initial value value when call reset',
74+
(tester) async {
75+
final formKey = GlobalKey<FormBuilderState>();
76+
const fieldName = 'phone';
77+
const initialValue = '1235';
78+
final testWidget = FormBuilderPhoneField(name: fieldName);
79+
await tester.pumpWidget(buildTestableFieldWidget(
80+
testWidget,
81+
formKey: formKey,
82+
initialValue: {fieldName: initialValue},
83+
));
84+
85+
formKey.currentState?.patchValue({fieldName: '+34649294281'});
86+
await tester.pumpAndSettle();
87+
formKey.currentState?.reset();
88+
89+
expect(formKey.currentState?.instantValue, {fieldName: initialValue});
90+
});
91+
testWidgets('should update valid phone when call patch value',
92+
(tester) async {
93+
final formKey = GlobalKey<FormBuilderState>();
94+
const fieldName = 'phone';
95+
const validPhone = '602299271';
96+
const validCodePhone = '+34';
97+
final testWidget = FormBuilderPhoneField(name: fieldName);
98+
await tester
99+
.pumpWidget(buildTestableFieldWidget(testWidget, formKey: formKey));
100+
101+
formKey.currentState
102+
?.patchValue({fieldName: '$validCodePhone$validPhone'});
103+
await tester.pumpAndSettle();
104+
105+
expect(formKey.currentState?.instantValue,
106+
{fieldName: '$validCodePhone$validPhone'});
107+
});
108+
});
109+
}
110+
111+
Widget buildTestableFieldWidget(
112+
Widget widget, {
113+
GlobalKey<FormBuilderState>? formKey,
114+
Map<String, dynamic> initialValue = const {},
115+
}) {
116+
return MaterialApp(
117+
home: Scaffold(
118+
body: FormBuilder(
119+
key: formKey ?? GlobalKey<FormBuilderFieldState>(),
120+
initialValue: initialValue,
121+
child: widget,
122+
),
123+
),
124+
);
5125
}

0 commit comments

Comments
 (0)