Skip to content

Commit 3630425

Browse files
committed
Started working on searchable_dropdown
1 parent a07cc0e commit 3630425

File tree

5 files changed

+199
-32
lines changed

5 files changed

+199
-32
lines changed

example/lib/sources/complete_form.dart

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class CompleteFormState extends State<CompleteForm> {
4848
children: <Widget>[
4949
FormBuilderFilterChip(
5050
name: 'filter_chip',
51-
decoration: InputDecoration(
51+
decoration: const InputDecoration(
5252
labelText: 'Select many options',
5353
),
5454
options: [
@@ -66,7 +66,7 @@ class CompleteFormState extends State<CompleteForm> {
6666
),
6767
FormBuilderChoiceChip(
6868
name: 'choice_chip',
69-
decoration: InputDecoration(
69+
decoration: const InputDecoration(
7070
labelText: 'Select an option',
7171
),
7272
options: [
@@ -86,10 +86,10 @@ class CompleteFormState extends State<CompleteForm> {
8686
name: 'color_picker',
8787
// initialValue: Colors.yellow,
8888
colorPickerType: ColorPickerType.MaterialPicker,
89-
decoration: InputDecoration(labelText: 'Pick Color'),
89+
decoration: const InputDecoration(labelText: 'Pick Color'),
9090
),
9191
FormBuilderChipsInput(
92-
decoration: InputDecoration(labelText: 'Chips'),
92+
decoration: const InputDecoration(labelText: 'Chips'),
9393
name: 'chips_test',
9494
onChanged: _onChanged,
9595
initialValue: [
@@ -144,7 +144,7 @@ class CompleteFormState extends State<CompleteForm> {
144144
FormBuilderDateTimePicker(
145145
name: 'date',
146146
inputType: InputType.time,
147-
decoration: InputDecoration(
147+
decoration: const InputDecoration(
148148
labelText: 'Appointment Time',
149149
),
150150
initialTime: TimeOfDay(hour: 8, minute: 0),
@@ -156,7 +156,7 @@ class CompleteFormState extends State<CompleteForm> {
156156
lastDate: DateTime(2030),
157157
format: DateFormat('yyyy-MM-dd'),
158158
onChanged: _onChanged,
159-
decoration: InputDecoration(
159+
decoration: const InputDecoration(
160160
labelText: 'Date Range',
161161
helperText: 'Helper text',
162162
hintText: 'Hint text',
@@ -174,7 +174,7 @@ class CompleteFormState extends State<CompleteForm> {
174174
divisions: 20,
175175
activeColor: Colors.red,
176176
inactiveColor: Colors.pink[100],
177-
decoration: InputDecoration(
177+
decoration: const InputDecoration(
178178
labelText: 'Number of things',
179179
),
180180
),
@@ -189,7 +189,7 @@ class CompleteFormState extends State<CompleteForm> {
189189
divisions: 20,
190190
activeColor: Colors.red,
191191
inactiveColor: Colors.pink[100],
192-
decoration: InputDecoration(
192+
decoration: const InputDecoration(
193193
labelText: 'Price Range',
194194
),
195195
),
@@ -280,7 +280,7 @@ class CompleteFormState extends State<CompleteForm> {
280280
},
281281
),
282282
FormBuilderTypeAhead(
283-
decoration: InputDecoration(
283+
decoration: const InputDecoration(
284284
labelText: 'Country',
285285
),
286286
name: 'country',
@@ -309,7 +309,7 @@ class CompleteFormState extends State<CompleteForm> {
309309
},
310310
),
311311
FormBuilderRadioGroup(
312-
decoration: InputDecoration(
312+
decoration: const InputDecoration(
313313
labelText: 'My chosen language',
314314
),
315315
name: 'best_language',
@@ -325,8 +325,8 @@ class CompleteFormState extends State<CompleteForm> {
325325
controlAffinity: ControlAffinity.trailing,
326326
),
327327
FormBuilderSegmentedControl(
328-
decoration:
329-
InputDecoration(labelText: 'Movie Rating (Archer)'),
328+
decoration: const InputDecoration(
329+
labelText: 'Movie Rating (Archer)'),
330330
name: 'movie_rating',
331331
// initialValue: 1,
332332
// textStyle: TextStyle(fontWeight: FontWeight.bold),
@@ -342,13 +342,13 @@ class CompleteFormState extends State<CompleteForm> {
342342
onChanged: _onChanged,
343343
),
344344
FormBuilderSwitch(
345-
title: Text('I Accept the tems and conditions'),
345+
title: const Text('I Accept the tems and conditions'),
346346
name: 'accept_terms_switch',
347347
initialValue: true,
348348
onChanged: _onChanged,
349349
),
350350
FormBuilderTouchSpin(
351-
decoration: InputDecoration(labelText: 'TouchSpin'),
351+
decoration: const InputDecoration(labelText: 'TouchSpin'),
352352
name: 'touch_spin',
353353
initialValue: 10,
354354
step: 1,
@@ -357,16 +357,17 @@ class CompleteFormState extends State<CompleteForm> {
357357
subtractIcon: Icon(Icons.arrow_left),
358358
),
359359
FormBuilderRating(
360-
decoration: InputDecoration(labelText: 'Rate this form'),
360+
decoration:
361+
const InputDecoration(labelText: 'Rate this form'),
361362
name: 'rate',
362363
iconSize: 32.0,
363364
initialValue: 1.0,
364365
max: 5.0,
365366
onChanged: _onChanged,
366367
),
367368
FormBuilderCheckboxGroup(
368-
decoration:
369-
InputDecoration(labelText: 'The language of my people'),
369+
decoration: const InputDecoration(
370+
labelText: 'The language of my people'),
370371
name: 'languages',
371372
initialValue: ['Dart'],
372373
options: [
@@ -384,7 +385,7 @@ class CompleteFormState extends State<CompleteForm> {
384385
),
385386
),
386387
FormBuilderSignaturePad(
387-
decoration: InputDecoration(
388+
decoration: const InputDecoration(
388389
labelText: 'Signature',
389390
border: OutlineInputBorder(),
390391
),
@@ -394,14 +395,14 @@ class CompleteFormState extends State<CompleteForm> {
394395
),
395396
FormBuilderImagePicker(
396397
name: 'photos',
397-
decoration: InputDecoration(labelText: 'Pick Photos'),
398+
decoration: const InputDecoration(labelText: 'Pick Photos'),
398399
maxImages: 1,
399400
),
400401
SizedBox(height: 15),
401402
FormBuilderCountryPicker(
402403
initialValue: 'Germany',
403404
name: 'country',
404-
decoration: InputDecoration(
405+
decoration: const InputDecoration(
405406
border: OutlineInputBorder(), labelText: 'Country'),
406407
validator: FormBuilderValidators.compose([
407408
FormBuilderValidators.required(context,
@@ -415,7 +416,7 @@ class CompleteFormState extends State<CompleteForm> {
415416
// defaultSelectedCountryIsoCode: 'KE',
416417
cursorColor: Colors.black,
417418
// style: TextStyle(color: Colors.black, fontSize: 18),
418-
decoration: InputDecoration(
419+
decoration: const InputDecoration(
419420
border: OutlineInputBorder(),
420421
labelText: 'Phone Number',
421422
hintText: 'Hint'),
@@ -428,15 +429,23 @@ class CompleteFormState extends State<CompleteForm> {
428429
errorText: 'This field required'),
429430
]),
430431
),
431-
/*SizedBox(height: 15),
432-
FormBuilderSignaturePad(
433-
decoration: InputDecoration(labelText: 'Signature'),
434-
name: 'signature',
435-
// height: 250,
436-
clearButtonText: 'Start Over',
437-
onChanged: _onChanged,
438-
),*/
439432
SizedBox(height: 15),
433+
FormBuilderSearchableDropdown<Contact>(
434+
decoration: InputDecoration(
435+
labelText: 'Phone Number',
436+
),
437+
name: 'searchable',
438+
items: contacts
439+
.map((e) => DropdownMenuItem(
440+
value: e,
441+
child: Text('${e.name}'),
442+
))
443+
.toList(),
444+
hint: 'Select one',
445+
searchHint: 'Select one',
446+
isExpanded: true,
447+
onChanged: _onChanged,
448+
),
440449
],
441450
),
442451
),
@@ -459,9 +468,7 @@ class CompleteFormState extends State<CompleteForm> {
459468
},
460469
),
461470
),
462-
SizedBox(
463-
width: 20,
464-
),
471+
SizedBox(width: 20),
465472
Expanded(
466473
child: OutlineButton(
467474
focusNode: FocusNode(),

lib/flutter_form_builder.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export './src/fields/form_builder_radio_group.dart';
2525
export './src/fields/form_builder_radio_list.dart';
2626
export './src/fields/form_builder_range_slider.dart';
2727
export './src/fields/form_builder_rating.dart';
28+
export './src/fields/form_builder_searchable_dropdown.dart';
2829
export './src/fields/form_builder_segmented_control.dart';
2930
export './src/fields/form_builder_signature_pad.dart';
3031
export './src/fields/form_builder_signature_pad.dart';
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import 'dart:ui';
2+
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter/widgets.dart';
5+
import 'package:flutter_form_builder/flutter_form_builder.dart';
6+
import 'package:searchable_dropdown/searchable_dropdown.dart';
7+
8+
class FormBuilderSearchableDropdown<T> extends FormBuilderField {
9+
final List<DropdownMenuItem<T>> items;
10+
final TextStyle style;
11+
final dynamic searchHint;
12+
final dynamic hint;
13+
final dynamic disabledHint;
14+
final dynamic icon;
15+
16+
final dynamic underline;
17+
final dynamic doneButton;
18+
final dynamic label;
19+
final dynamic closeButton;
20+
21+
final bool displayClearIcon;
22+
23+
final Icon clearIcon;
24+
25+
final Color iconEnabledColor;
26+
final Color iconDisabledColor;
27+
final double iconSize;
28+
final bool isExpanded;
29+
30+
final bool isCaseSensitiveSearch;
31+
final Function searchFn;
32+
final Function onClear;
33+
final Function selectedValueWidgetFn;
34+
final TextInputType keyboardType;
35+
36+
final bool assertUniqueValue;
37+
final Function displayItem;
38+
final bool dialogBox;
39+
final BoxConstraints menuConstraints;
40+
final Color menuBackgroundColor;
41+
42+
FormBuilderSearchableDropdown({
43+
Key key,
44+
//From Super
45+
@required String name,
46+
FormFieldValidator validator,
47+
T initialValue,
48+
bool readOnly = false,
49+
InputDecoration decoration = const InputDecoration(),
50+
ValueChanged onChanged,
51+
ValueTransformer valueTransformer,
52+
bool enabled = true,
53+
FormFieldSetter onSaved,
54+
bool autovalidate = false,
55+
VoidCallback onReset,
56+
FocusNode focusNode,
57+
@required this.items,
58+
this.style,
59+
this.searchHint,
60+
this.hint,
61+
this.disabledHint,
62+
this.icon = const Icon(Icons.arrow_drop_down),
63+
this.underline,
64+
this.doneButton,
65+
this.label,
66+
this.closeButton = 'Close',
67+
this.displayClearIcon = true,
68+
this.clearIcon = const Icon(Icons.clear),
69+
this.iconEnabledColor,
70+
this.iconDisabledColor,
71+
this.iconSize = 24.0,
72+
this.isExpanded = false,
73+
this.isCaseSensitiveSearch = false,
74+
this.searchFn,
75+
this.onClear,
76+
this.selectedValueWidgetFn,
77+
this.keyboardType = TextInputType.text,
78+
this.assertUniqueValue = true,
79+
this.displayItem,
80+
this.dialogBox = true,
81+
this.menuConstraints,
82+
this.menuBackgroundColor,
83+
}) : super(
84+
key: key,
85+
initialValue: initialValue,
86+
name: name,
87+
validator: validator,
88+
valueTransformer: valueTransformer,
89+
onChanged: onChanged,
90+
readOnly: readOnly,
91+
autovalidate: autovalidate,
92+
onSaved: onSaved,
93+
enabled: enabled,
94+
onReset: onReset,
95+
decoration: decoration,
96+
builder: (FormFieldState field) {
97+
final _FormBuilderSearchableDropdownState state = field;
98+
99+
return InputDecorator(
100+
decoration: decoration.copyWith(
101+
enabled: state.readOnly,
102+
errorText: decoration?.errorText ?? field.errorText,
103+
),
104+
child: SearchableDropdown.single(
105+
items: items,
106+
onChanged: (val){
107+
state.didChange(val);
108+
},
109+
// value: state.value,
110+
style: style,
111+
searchHint: searchHint,
112+
hint: hint,
113+
disabledHint: disabledHint,
114+
icon: icon,
115+
underline: underline,
116+
doneButton: doneButton,
117+
label: label,
118+
closeButton: closeButton,
119+
displayClearIcon: displayClearIcon,
120+
clearIcon: clearIcon,
121+
iconEnabledColor: iconEnabledColor,
122+
iconDisabledColor: iconDisabledColor,
123+
iconSize: iconSize,
124+
isExpanded: isExpanded,
125+
isCaseSensitiveSearch: isCaseSensitiveSearch,
126+
searchFn: searchFn,
127+
onClear: onClear,
128+
selectedValueWidgetFn: selectedValueWidgetFn,
129+
keyboardType: keyboardType,
130+
validator: validator,
131+
// assertUniqueValue: assertUniqueValue,
132+
displayItem: displayItem,
133+
dialogBox: dialogBox,
134+
menuConstraints: menuConstraints,
135+
readOnly: readOnly,
136+
menuBackgroundColor: menuBackgroundColor,
137+
),
138+
);
139+
},
140+
);
141+
142+
@override
143+
_FormBuilderSearchableDropdownState createState() =>
144+
_FormBuilderSearchableDropdownState();
145+
}
146+
147+
class _FormBuilderSearchableDropdownState extends FormBuilderFieldState {
148+
@override
149+
FormBuilderSearchableDropdown get widget =>
150+
super.widget as FormBuilderSearchableDropdown;
151+
}

pubspec.lock

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,13 @@ packages:
436436
url: "https://pub.dartlang.org"
437437
source: hosted
438438
version: "0.2.0"
439+
searchable_dropdown:
440+
dependency: "direct main"
441+
description:
442+
name: searchable_dropdown
443+
url: "https://pub.dartlang.org"
444+
source: hosted
445+
version: "1.1.3"
439446
shelf:
440447
dependency: transitive
441448
description:

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies:
2727
signature: ^3.2.0
2828
validators: ^2.0.1
2929
flutter_datetime_picker: ^1.3.8
30+
searchable_dropdown: ^1.1.3
3031

3132
dev_dependencies:
3233
flutter_test:

0 commit comments

Comments
 (0)