Skip to content

Commit c8fbcc4

Browse files
feat: add error builder property
1 parent 75054aa commit c8fbcc4

File tree

5 files changed

+70
-11
lines changed

5 files changed

+70
-11
lines changed

example/pubspec.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ packages:
55
dependency: transitive
66
description:
77
name: async
8-
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
8+
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
99
url: "https://pub.dev"
1010
source: hosted
11-
version: "2.12.0"
11+
version: "2.13.0"
1212
boolean_selector:
1313
dependency: transitive
1414
description:

lib/src/form_builder_field.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class FormBuilderField<T> extends FormField<T> {
5353
super.validator,
5454
super.restorationId,
5555
required super.builder,
56+
super.errorBuilder,
5657
required this.name,
5758
this.valueTransformer,
5859
this.onChanged,

lib/src/form_builder_field_decoration.dart

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class FormBuilderFieldDecoration<T> extends FormBuilderField<T> {
1919
super.onChanged,
2020
super.onReset,
2121
super.focusNode,
22+
super.errorBuilder,
2223
required super.builder,
2324
this.decoration = const InputDecoration(),
2425
}) : assert(
@@ -45,15 +46,25 @@ class FormBuilderFieldDecorationState<
4546
F get widget => super.widget as F;
4647

4748
/// Get the decoration with the current state
48-
InputDecoration get decoration => widget.decoration.copyWith(
49-
// Read only allow show error to support property skipDisabled
50-
errorText:
49+
InputDecoration get decoration {
50+
final String? efectiveErrorText =
5151
widget.enabled || readOnly
5252
? widget.decoration.errorText ?? errorText
53-
: null,
54-
enabled:
55-
widget.decoration.enabled ? widget.enabled : widget.decoration.enabled,
56-
);
53+
: null;
54+
55+
return widget.decoration.copyWith(
56+
// Read only allow show error to support property skipDisabled
57+
errorText: widget.errorBuilder != null ? null : efectiveErrorText,
58+
error:
59+
widget.errorBuilder != null && efectiveErrorText != null
60+
? widget.errorBuilder!(context, efectiveErrorText)
61+
: null,
62+
enabled:
63+
widget.decoration.enabled
64+
? widget.enabled
65+
: widget.decoration.enabled,
66+
);
67+
}
5768

5869
@override
5970
bool get hasError => super.hasError || widget.decoration.errorText != null;

pubspec.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ packages:
55
dependency: transitive
66
description:
77
name: async
8-
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
8+
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
99
url: "https://pub.dev"
1010
source: hosted
11-
version: "2.12.0"
11+
version: "2.13.0"
1212
boolean_selector:
1313
dependency: transitive
1414
description:

test/src/form_builder_field_decoration_test.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,53 @@ void main() {
4343
// The field should be valid again
4444
expect(decorationFieldKey.currentState?.isValid, isTrue);
4545
});
46+
47+
testWidgets('when set errorBuilder then show a custom widget on error', (
48+
widgetTester,
49+
) async {
50+
final decorationFieldKey = GlobalKey<FormBuilderFieldDecorationState>();
51+
const name = 'testField';
52+
const errorTextField = 'error text field';
53+
final errorTextKey = Key('errorTextKey');
54+
final widget = FormBuilderFieldDecoration<String>(
55+
key: decorationFieldKey,
56+
name: name,
57+
errorBuilder: (context, errorText) {
58+
return Text(
59+
errorText,
60+
key: errorTextKey,
61+
style: const TextStyle(color: Colors.red),
62+
);
63+
},
64+
builder: (FormFieldState<String?> field) {
65+
return InputDecorator(
66+
decoration: (field as FormBuilderFieldDecorationState).decoration,
67+
child: TextField(
68+
onChanged: (value) {
69+
field.didChange(value);
70+
},
71+
),
72+
);
73+
},
74+
);
75+
76+
await widgetTester.pumpWidget(buildTestableFieldWidget(widget));
77+
78+
// Initially, the field should be valid
79+
expect(decorationFieldKey.currentState?.isValid, isTrue);
80+
81+
decorationFieldKey.currentState?.invalidate(errorTextField);
82+
83+
// The field should be invalid
84+
expect(decorationFieldKey.currentState?.isValid, isFalse);
85+
86+
await widgetTester.pumpAndSettle();
87+
88+
// Check if the custom error widget is displayed
89+
expect(find.text(errorTextField), findsOneWidget);
90+
expect(find.byKey(errorTextKey), findsOneWidget);
91+
});
92+
4693
group('decoration enabled -', () {
4794
testWidgets(
4895
'when change the error text then the field should be invalid',

0 commit comments

Comments
 (0)