Skip to content

Commit 7f542eb

Browse files
Merge pull request #1346 from freemansoft/features/synch-grouped-radio-checkbox
Add PR 1106 GroupedRadio separator behavior to GroupedCheckbox
2 parents 66d87f0 + caa0699 commit 7f542eb

File tree

5 files changed

+293
-6
lines changed

5 files changed

+293
-6
lines changed

example/lib/main.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:example/sources/conditional_fields.dart';
22
import 'package:example/sources/decorated_radio_checkbox.dart';
33
import 'package:example/sources/dynamic_fields.dart';
4+
import 'package:example/sources/grouped_radio_checkbox.dart';
45
import 'package:example/sources/related_fields.dart';
56
import 'package:flutter/material.dart';
67
import 'package:flutter_localizations/flutter_localizations.dart';
@@ -162,6 +163,23 @@ class _HomePage extends StatelessWidget {
162163
);
163164
},
164165
),
166+
const Divider(),
167+
ListTile(
168+
title: const Text('GroupedRadio and GroupedCheckbox Orientation'),
169+
trailing: const Icon(Icons.arrow_right_sharp),
170+
onTap: () {
171+
Navigator.of(context).push(
172+
MaterialPageRoute(
173+
builder: (context) {
174+
return const CodePage(
175+
title: 'GroupedRadio and GroupedCheckbox',
176+
child: GroupedRadioCheckbox(),
177+
);
178+
},
179+
),
180+
);
181+
},
182+
),
165183
],
166184
),
167185
);
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_form_builder/flutter_form_builder.dart';
3+
import 'package:form_builder_validators/form_builder_validators.dart';
4+
5+
class GroupedRadioCheckbox extends StatefulWidget {
6+
const GroupedRadioCheckbox({Key? key}) : super(key: key);
7+
8+
@override
9+
State<GroupedRadioCheckbox> createState() {
10+
return _GroupedRadioCheckbox();
11+
}
12+
}
13+
14+
class _GroupedRadioCheckbox extends State<GroupedRadioCheckbox> {
15+
bool autoValidate = true;
16+
bool readOnly = false;
17+
bool showSegmentedControl = true;
18+
final _formKey = GlobalKey<FormBuilderState>();
19+
20+
var genderOptions = ['Male', 'Female', 'Other'];
21+
22+
void _onChanged(dynamic val) => debugPrint(val.toString());
23+
24+
@override
25+
Widget build(BuildContext context) {
26+
return SingleChildScrollView(
27+
child: Column(
28+
children: <Widget>[
29+
FormBuilder(
30+
key: _formKey,
31+
// enabled: false,
32+
onChanged: () {
33+
_formKey.currentState!.save();
34+
debugPrint(_formKey.currentState!.value.toString());
35+
},
36+
autovalidateMode: AutovalidateMode.disabled,
37+
initialValue: const {
38+
'movie_rating': 5,
39+
'best_language': 'Dart',
40+
'age': '13',
41+
'gender': 'Male',
42+
'languages_filter': ['Dart']
43+
},
44+
skipDisabled: true,
45+
child: Column(
46+
children: <Widget>[
47+
//
48+
const SizedBox(height: 15),
49+
FormBuilderRadioGroup<String>(
50+
decoration: const InputDecoration(
51+
labelText: 'My chosen language',
52+
),
53+
initialValue: null,
54+
name: 'best_language_horiz',
55+
onChanged: _onChanged,
56+
separator: const SizedBox(
57+
width: 8.0,
58+
height: 8.0,
59+
child: DecoratedBox(
60+
decoration: BoxDecoration(color: Colors.red),
61+
),
62+
),
63+
validator: FormBuilderValidators.compose(
64+
[FormBuilderValidators.required()]),
65+
options: ['Dart', 'Kotlin', 'Java', 'Swift', 'Objective-C']
66+
.map((lang) => FormBuilderFieldOption(
67+
value: lang,
68+
child: Text(lang),
69+
))
70+
.toList(growable: false),
71+
controlAffinity: ControlAffinity.leading,
72+
orientation: OptionsOrientation.wrap,
73+
),
74+
//
75+
const SizedBox(height: 15),
76+
FormBuilderRadioGroup<String>(
77+
decoration: const InputDecoration(
78+
labelText: 'My chosen language',
79+
),
80+
initialValue: null,
81+
name: 'best_language_vert',
82+
onChanged: _onChanged,
83+
separator: const SizedBox(
84+
width: 8.0,
85+
height: 8.0,
86+
child: DecoratedBox(
87+
decoration: BoxDecoration(color: Colors.red),
88+
),
89+
),
90+
validator: FormBuilderValidators.compose(
91+
[FormBuilderValidators.required()]),
92+
options: ['Dart', 'Kotlin', 'Java', 'Swift', 'Objective-C']
93+
.map((lang) => FormBuilderFieldOption(
94+
value: lang,
95+
child: Text(lang),
96+
))
97+
.toList(growable: false),
98+
controlAffinity: ControlAffinity.leading,
99+
orientation: OptionsOrientation.vertical,
100+
),
101+
//
102+
const SizedBox(height: 15),
103+
FormBuilderCheckboxGroup<String>(
104+
autovalidateMode: AutovalidateMode.onUserInteraction,
105+
decoration: const InputDecoration(
106+
labelText: 'The language of my people'),
107+
name: 'languages_horiz',
108+
// initialValue: const ['Dart'],
109+
options: const [
110+
FormBuilderFieldOption(value: 'Dart'),
111+
FormBuilderFieldOption(value: 'Kotlin'),
112+
FormBuilderFieldOption(value: 'Java'),
113+
FormBuilderFieldOption(value: 'Swift'),
114+
FormBuilderFieldOption(value: 'Objective-C'),
115+
],
116+
onChanged: _onChanged,
117+
separator: const SizedBox(
118+
width: 8.0,
119+
height: 8.0,
120+
child: DecoratedBox(
121+
decoration: BoxDecoration(color: Colors.red),
122+
),
123+
),
124+
validator: FormBuilderValidators.compose([
125+
FormBuilderValidators.minLength(1),
126+
FormBuilderValidators.maxLength(3),
127+
]),
128+
orientation: OptionsOrientation.wrap,
129+
),
130+
//
131+
const SizedBox(height: 15),
132+
FormBuilderCheckboxGroup<String>(
133+
autovalidateMode: AutovalidateMode.onUserInteraction,
134+
decoration: const InputDecoration(
135+
labelText: 'The language of my people'),
136+
name: 'languages_vert',
137+
// initialValue: const ['Dart'],
138+
options: const [
139+
FormBuilderFieldOption(value: 'Dart'),
140+
FormBuilderFieldOption(value: 'Kotlin'),
141+
FormBuilderFieldOption(value: 'Java'),
142+
FormBuilderFieldOption(value: 'Swift'),
143+
FormBuilderFieldOption(value: 'Objective-C'),
144+
],
145+
onChanged: _onChanged,
146+
separator: const SizedBox(
147+
width: 8.0,
148+
height: 8.0,
149+
child: DecoratedBox(
150+
decoration: BoxDecoration(color: Colors.red),
151+
),
152+
),
153+
validator: FormBuilderValidators.compose([
154+
FormBuilderValidators.minLength(1),
155+
FormBuilderValidators.maxLength(3),
156+
]),
157+
orientation: OptionsOrientation.vertical,
158+
),
159+
],
160+
),
161+
),
162+
],
163+
),
164+
);
165+
}
166+
}

lib/src/widgets/grouped_checkbox.dart

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,26 @@ class GroupedCheckbox<T> extends StatelessWidget {
295295
child: option,
296296
);
297297

298-
Widget compositeItem = Row(
298+
Widget compositeItem = Column(
299299
mainAxisSize: MainAxisSize.min,
300-
children: <Widget>[
301-
if (controlAffinity == ControlAffinity.leading) control,
302-
Flexible(flex: 1, child: label),
303-
if (controlAffinity == ControlAffinity.trailing) control,
304-
if (separator != null && index != options.length - 1) separator!,
300+
crossAxisAlignment: CrossAxisAlignment.start,
301+
children: [
302+
Row(
303+
mainAxisSize: MainAxisSize.min,
304+
children: <Widget>[
305+
if (controlAffinity == ControlAffinity.leading) control,
306+
Flexible(flex: 1, child: label),
307+
if (controlAffinity == ControlAffinity.trailing) control,
308+
if (orientation != OptionsOrientation.vertical &&
309+
separator != null &&
310+
index != options.length - 1)
311+
separator!,
312+
],
313+
),
314+
if (orientation == OptionsOrientation.vertical &&
315+
separator != null &&
316+
index != options.length - 1)
317+
separator!,
305318
],
306319
);
307320

test/form_builder_checkbox_group_test.dart

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ void main() {
5151
// same as wrapSpacing
5252
Container foo = tester.firstWidget(find.byType(Container));
5353
expect(foo.margin, const EdgeInsets.only(right: 10.0));
54+
// verify separator counts
55+
expect(find.byType(VerticalDivider), findsNothing);
5456
});
5557

5658
testWidgets('FormBuilderCheckboxGroup -- decoration vertical',
@@ -75,8 +77,49 @@ void main() {
7577
// same as wrapSpacing
7678
Container foo = tester.firstWidget(find.byType(Container));
7779
expect(foo.margin, const EdgeInsets.only(bottom: 10.0));
80+
// verify separator counts
81+
expect(find.byType(VerticalDivider), findsNothing);
7882
});
7983

84+
testWidgets('FormBuilderCheckboxGroup -- separator horizontal',
85+
(WidgetTester tester) async {
86+
const widgetName = 'cbg1';
87+
final testWidget = FormBuilderCheckboxGroup<int>(
88+
name: widgetName,
89+
orientation: OptionsOrientation.horizontal,
90+
wrapSpacing: 10.0,
91+
options: const [
92+
FormBuilderFieldOption(key: ValueKey('1'), value: 1),
93+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
94+
FormBuilderFieldOption(key: ValueKey('3'), value: 2),
95+
],
96+
separator: const VerticalDivider(width: 8.0, color: Colors.red),
97+
);
98+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
99+
100+
// verify separator counts
101+
expect(find.byType(VerticalDivider), findsNWidgets(2));
102+
});
103+
104+
testWidgets('FormBuilderCheckboxGroup -- separator vertical',
105+
(WidgetTester tester) async {
106+
const widgetName = 'cbg1';
107+
final testWidget = FormBuilderCheckboxGroup<int>(
108+
name: widgetName,
109+
orientation: OptionsOrientation.vertical,
110+
wrapSpacing: 10.0,
111+
options: const [
112+
FormBuilderFieldOption(key: ValueKey('1'), value: 1),
113+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
114+
FormBuilderFieldOption(key: ValueKey('3'), value: 2),
115+
],
116+
separator: const VerticalDivider(width: 8.0, color: Colors.red),
117+
);
118+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
119+
120+
// verify separator counts
121+
expect(find.byType(VerticalDivider), findsNWidgets(2));
122+
});
80123
testWidgets('FormBuilderCheckboxGroup -- didChange',
81124
(WidgetTester tester) async {
82125
const fieldName = 'cbg1';

test/form_builder_radio_group_test.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ void main() {
5050
// same as wrapSpacing
5151
Container foo = tester.firstWidget(find.byType(Container));
5252
expect(foo.margin, const EdgeInsets.only(right: 10.0));
53+
// verify separator counts
54+
expect(find.byType(VerticalDivider), findsNothing);
5355
});
5456

5557
testWidgets('FormBuilderRadioGroup -- decoration vertical',
@@ -74,5 +76,50 @@ void main() {
7476
// same as wrapSpacing
7577
Container foo = tester.firstWidget(find.byType(Container));
7678
expect(foo.margin, const EdgeInsets.only(bottom: 10.0));
79+
// verify separator counts
80+
expect(find.byType(VerticalDivider), findsNothing);
81+
});
82+
83+
testWidgets('FormBuilderRadioGroup -- separators horizontal',
84+
(WidgetTester tester) async {
85+
const widgetName = 'rg1';
86+
final testWidget = FormBuilderRadioGroup<int>(
87+
name: widgetName,
88+
orientation: OptionsOrientation.horizontal,
89+
wrapSpacing: 10.0,
90+
options: const [
91+
FormBuilderFieldOption(key: ValueKey('1'), value: 1),
92+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
93+
FormBuilderFieldOption(key: ValueKey('3'), value: 2),
94+
],
95+
separator: const VerticalDivider(width: 8.0, color: Colors.red),
96+
);
97+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
98+
99+
// verify separator counts
100+
expect(find.byType(VerticalDivider), findsNWidgets(2));
101+
});
102+
103+
testWidgets('FormBuilderRadioGroup -- separators vertical',
104+
(WidgetTester tester) async {
105+
const widgetName = 'rg1';
106+
final testWidget = FormBuilderRadioGroup<int>(
107+
name: widgetName,
108+
orientation: OptionsOrientation.vertical,
109+
wrapSpacing: 10.0,
110+
options: const [
111+
FormBuilderFieldOption(key: ValueKey('1'), value: 1),
112+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
113+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
114+
],
115+
itemDecoration: BoxDecoration(
116+
border: Border.all(color: Colors.blueAccent),
117+
),
118+
separator: const VerticalDivider(width: 8.0, color: Colors.red),
119+
);
120+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
121+
122+
// verify separator counts
123+
expect(find.byType(VerticalDivider), findsNWidgets(2));
77124
});
78125
}

0 commit comments

Comments
 (0)