Skip to content

Commit 6421658

Browse files
feat: improve extension of with context
1 parent fffb27d commit 6421658

4 files changed

Lines changed: 70 additions & 60 deletions

File tree

example/lib/minimal_code_example.dart

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_form_builder/flutter_form_builder.dart';
3-
import 'package:flutter_localizations/flutter_localizations.dart';
4-
import 'package:form_builder_validators/form_builder_validators.dart';
53

64
void main() => runApp(const MyApp());
75

@@ -13,12 +11,6 @@ class MyApp extends StatelessWidget {
1311
return MaterialApp(
1412
title: 'Flutter FormBuilder Example',
1513
debugShowCheckedModeBanner: false,
16-
localizationsDelegates: const [
17-
FormBuilderLocalizations.delegate,
18-
...GlobalMaterialLocalizations.delegates,
19-
GlobalWidgetsLocalizations.delegate,
20-
],
21-
supportedLocales: FormBuilderLocalizations.supportedLocales,
2214
home: const _ExamplePage(),
2315
);
2416
}
@@ -37,56 +29,47 @@ class _ExamplePageState extends State<_ExamplePage> {
3729
@override
3830
Widget build(BuildContext context) {
3931
return Scaffold(
40-
appBar: AppBar(title: const Text('Minimal code example')),
41-
body: Padding(
42-
padding: const EdgeInsets.all(16),
43-
child: FormBuilder(
44-
key: _formKey,
45-
child: Column(
46-
children: [
47-
FormBuilderFilterChips<String>(
48-
decoration: const InputDecoration(
49-
labelText: 'The language of my people',
50-
),
51-
name: 'languages_filter',
52-
selectedColor: Colors.red,
53-
options: const [
54-
FormBuilderChipOption(
55-
value: 'Dart',
56-
avatar: CircleAvatar(child: Text('D')),
32+
body: SafeArea(
33+
child: Column(
34+
children: [
35+
FormBuilder(
36+
key: _formKey,
37+
child: Column(
38+
children: [
39+
FormBuilderTextField(
40+
name: 'full_name',
41+
decoration: const InputDecoration(labelText: 'Full Name'),
42+
validator: (value) {
43+
if (value == null || value.isEmpty) {
44+
return 'Please enter your full name';
45+
}
46+
return null;
47+
},
5748
),
58-
FormBuilderChipOption(
59-
value: 'Kotlin',
60-
avatar: CircleAvatar(child: Text('K')),
61-
),
62-
FormBuilderChipOption(
63-
value: 'Java',
64-
avatar: CircleAvatar(child: Text('J')),
65-
),
66-
FormBuilderChipOption(
67-
value: 'Swift',
68-
avatar: CircleAvatar(child: Text('S')),
69-
),
70-
FormBuilderChipOption(
71-
value: 'Objective-C',
72-
avatar: CircleAvatar(child: Text('O')),
49+
Builder(
50+
builder: (innerContext) {
51+
return Text(
52+
FormBuilder.of(innerContext).isValid
53+
? 'OK Valid'
54+
: 'X Invalid',
55+
);
56+
},
7357
),
58+
const SizedBox(height: 10),
59+
Builder(builder: (innerContext) {
60+
return ElevatedButton(
61+
onPressed: () {
62+
FormBuilder.of(innerContext).saveAndValidate();
63+
debugPrint(
64+
FormBuilder.of(innerContext).value.toString());
65+
},
66+
child: const Text('Print'),
67+
);
68+
}),
7469
],
75-
validator: FormBuilderValidators.compose([
76-
FormBuilderValidators.minLength(1),
77-
FormBuilderValidators.maxLength(3),
78-
]),
7970
),
80-
const SizedBox(height: 10),
81-
ElevatedButton(
82-
onPressed: () {
83-
_formKey.currentState?.saveAndValidate();
84-
debugPrint(_formKey.currentState?.value.toString());
85-
},
86-
child: const Text('Print'),
87-
)
88-
],
89-
),
71+
),
72+
],
9073
),
9174
),
9275
);

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.dart

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,35 @@ class FormBuilder extends StatefulWidget {
110110
this.canPop,
111111
});
112112

113-
static FormBuilderState? of(BuildContext context) =>
114-
context.findAncestorStateOfType<FormBuilderState>();
113+
static FormBuilderState of(BuildContext context, [bool listen = false]) {
114+
final FormBuilderState? formState = maybeOf(context, listen);
115+
assert(() {
116+
if (formState == null) {
117+
throw FlutterError(
118+
'FormBuilder.of() was called with a context that does not contain a FormBuilder widget.\n'
119+
'No FormBuilder widget ancestor could be found starting from the context that '
120+
'was passed to FormBuilder.of(). This can happen because you are using a widget '
121+
'that looks for a FormBuilder ancestor, but no such ancestor exists.\n'
122+
'The context used was:\n'
123+
' $context',
124+
);
125+
}
126+
return true;
127+
}());
128+
return formState!;
129+
}
130+
131+
static FormBuilderState? maybeOf(
132+
BuildContext context, [
133+
bool listen = false,
134+
]) {
135+
if (listen) {
136+
return context
137+
.dependOnInheritedWidgetOfExactType<_FormBuilderScope>()
138+
?._formState;
139+
}
140+
return context.findAncestorStateOfType<FormBuilderState>();
141+
}
115142

116143
@override
117144
FormBuilderState createState() => FormBuilderState();

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:

0 commit comments

Comments
 (0)