@@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart';
4
4
import 'package:flutter/material.dart' ;
5
5
import 'package:flutter/widgets.dart' ;
6
6
import 'package:flutter_form_builder/flutter_form_builder.dart' ;
7
+ import 'package:flutter_form_builder/src/country_picker_util.dart' ;
7
8
8
9
class FormBuilderCountryPicker extends StatefulWidget {
9
10
final String attribute;
@@ -21,6 +22,7 @@ class FormBuilderCountryPicker extends StatefulWidget {
21
22
final EdgeInsets titlePadding;
22
23
final bool isSearchable;
23
24
final Text dialogTitle;
25
+ final String initialValue;
24
26
final String defaultSelectedCountryIsoCode;
25
27
final List <String > priorityListByIsoCode;
26
28
final List <String > countryFilterByIsoCode;
@@ -29,154 +31,105 @@ class FormBuilderCountryPicker extends StatefulWidget {
29
31
final double cupertinoPickerSheetHeight;
30
32
final Color cursorColor;
31
33
32
- FormBuilderCountryPicker (
33
- {Key key,
34
- @required this .attribute,
35
- this .validators = const [],
36
- this .readOnly = false ,
37
- this .decoration = const InputDecoration (),
38
- this .style,
39
- this .onChanged,
40
- this .valueTransformer,
41
- this .onSaved,
42
- this .searchText,
43
- this .titlePadding,
44
- this .dialogTitle,
45
- this .isSearchable,
46
- @required this .defaultSelectedCountryIsoCode,
47
- this .priorityListByIsoCode,
48
- this .countryFilterByIsoCode,
49
- this .dialogTextStyle,
50
- this .isCupertinoPicker,
51
- this .cupertinoPickerSheetHeight,
52
- this .cursorColor})
53
- : assert (defaultSelectedCountryIsoCode != null ),
34
+ FormBuilderCountryPicker ({
35
+ Key key,
36
+ @required this .attribute,
37
+ this .defaultSelectedCountryIsoCode = "US" ,
38
+ this .initialValue,
39
+ this .validators = const [],
40
+ this .readOnly = false ,
41
+ this .decoration = const InputDecoration (),
42
+ this .style,
43
+ this .onChanged,
44
+ this .valueTransformer,
45
+ this .onSaved,
46
+ this .searchText,
47
+ this .titlePadding,
48
+ this .dialogTitle,
49
+ this .isSearchable,
50
+ this .priorityListByIsoCode,
51
+ this .countryFilterByIsoCode,
52
+ this .dialogTextStyle,
53
+ this .isCupertinoPicker = false ,
54
+ this .cupertinoPickerSheetHeight,
55
+ this .cursorColor,
56
+ }) : assert (initialValue != null ),
54
57
super (key: key);
55
58
56
59
@override
57
- _FormBuilderCountryPickerState createState () => _FormBuilderCountryPickerState ();
60
+ _FormBuilderCountryPickerState createState () =>
61
+ _FormBuilderCountryPickerState ();
58
62
}
59
63
60
64
class _FormBuilderCountryPickerState extends State <FormBuilderCountryPicker > {
61
65
bool _readOnly = false ;
62
66
final GlobalKey <FormFieldState > _fieldKey = GlobalKey <FormFieldState >();
63
67
FormBuilderState _formState;
64
- Country _selectedDialogCountry;
65
-
66
- void _openCupertinoCountryPicker () => showCupertinoModalPopup <void >(
67
- context: context,
68
- builder: (BuildContext context) {
69
- return CountryPickerCupertino (
70
- pickerSheetHeight: widget.cupertinoPickerSheetHeight ?? 300.0 ,
71
- onValuePicked: (Country country) => setState (() => _selectedDialogCountry = country),
72
- itemFilter: widget.countryFilterByIsoCode != null
73
- ? (c) => widget.countryFilterByIsoCode.contains (c.isoCode)
74
- : null ,
75
- priorityList: widget.priorityListByIsoCode != null
76
- ? List .generate (widget.priorityListByIsoCode.length,
77
- (index) => CountryPickerUtils .getCountryByIsoCode (widget.priorityListByIsoCode[index]))
78
- : null ,
79
- );
80
- },
81
- );
82
-
83
- void _openCountryPickerDialog () => showDialog (
84
- context: context,
85
- builder: (context) => Theme (
86
- data: Theme .of (context).copyWith (
87
- cursorColor: Theme .of (context).primaryColor,
88
- primaryColor: widget.cursorColor ?? Theme .of (context).primaryColor,
89
- ),
90
- child: CountryPickerDialog (
91
- titlePadding: widget.titlePadding ?? EdgeInsets .all (8.0 ),
92
- searchCursorColor: widget.cursorColor ?? Theme .of (context).primaryColor,
93
- searchInputDecoration: InputDecoration (hintText: widget.searchText ?? 'Search...' ),
94
- isSearchable: widget.isSearchable ?? true ,
95
- title: widget.dialogTitle ??
96
- Text (
97
- 'Select Your Country' ,
98
- style: widget.dialogTextStyle ?? widget.style,
99
- ),
100
- onValuePicked: (Country country) => setState (() => _selectedDialogCountry = country),
101
- itemFilter: widget.countryFilterByIsoCode != null
102
- ? (c) => widget.countryFilterByIsoCode.contains (c.isoCode)
103
- : null ,
104
- priorityList: widget.priorityListByIsoCode != null
105
- ? List .generate (widget.priorityListByIsoCode.length,
106
- (index) => CountryPickerUtils .getCountryByIsoCode (widget.priorityListByIsoCode[index]))
107
- : null ,
108
- itemBuilder: _buildDialogItem,
109
- ),
110
- ),
111
- );
112
-
113
- Widget _buildDialogItem (Country country) => Container (
114
- child: ListTile (
115
- contentPadding: EdgeInsets .zero,
116
- leading: CountryPickerUtils .getDefaultFlagImage (country),
117
- title: Text ("${country .name }" ),
118
- visualDensity: VisualDensity .compact,
119
- ),
120
- );
68
+ Country _initialValue;
121
69
122
70
@override
123
71
void initState () {
124
72
_formState = FormBuilder .of (context);
125
73
_formState? .registerFieldKey (widget.attribute, _fieldKey);
126
- _selectedDialogCountry = CountryPickerUtils .getCountryByIsoCode (widget.defaultSelectedCountryIsoCode);
127
-
74
+ _initialValue =
75
+ CountryPickerUtil .getCountryByCodeOrName (widget.initialValue) ??
76
+ CountryPickerUtil .getCountryByIsoCode (
77
+ widget.defaultSelectedCountryIsoCode);
128
78
super .initState ();
129
79
}
130
80
131
- @override
132
- void dispose () {
133
- _formState? .unregisterFieldKey (widget.attribute);
134
- super .dispose ();
135
- }
136
-
137
81
@override
138
82
Widget build (BuildContext context) {
139
83
_readOnly = (_formState? .readOnly == true ) ? true : widget.readOnly;
140
84
141
85
return FormField <Country >(
142
86
key: _fieldKey,
143
87
enabled: ! _readOnly,
144
- initialValue: CountryPickerUtils . getCountryByIsoCode (widget.defaultSelectedCountryIsoCode) ,
88
+ initialValue: _initialValue ,
145
89
validator: (val) {
146
90
for (int i = 0 ; i < widget.validators.length; i++ ) {
147
- if (widget.validators[i](val) != null ) return widget.validators[i](val);
91
+ if (widget.validators[i](val) != null ) {
92
+ return widget.validators[i](val);
93
+ }
148
94
}
149
95
return null ;
150
96
},
151
97
onSaved: (val) {
152
98
dynamic transformed;
153
99
if (widget.valueTransformer != null ) {
154
- transformed = widget.valueTransformer (_selectedDialogCountry );
100
+ transformed = widget.valueTransformer (val );
155
101
_formState? .setAttributeValue (widget.attribute, transformed);
156
- } else
157
- _formState? .setAttributeValue (widget.attribute, _selectedDialogCountry.name);
102
+ } else {
103
+ _formState? .setAttributeValue (widget.attribute, val.name);
104
+ }
158
105
if (widget.onSaved != null ) {
159
- widget.onSaved (transformed ?? _selectedDialogCountry .name);
106
+ widget.onSaved (transformed ?? val .name);
160
107
}
161
108
},
162
109
builder: (FormFieldState <Country > field) {
163
110
return GestureDetector (
164
- onTap: widget.isCupertinoPicker != null
165
- ? (widget.isCupertinoPicker ? _openCupertinoCountryPicker : _openCountryPickerDialog)
166
- : _openCountryPickerDialog,
111
+ onTap: () {
112
+ FocusScope .of (context).requestFocus (FocusNode ());
113
+ if (widget.isCupertinoPicker) {
114
+ _openCupertinoCountryPicker (field);
115
+ } else {
116
+ _openCountryPickerDialog (field);
117
+ }
118
+ },
167
119
child: InputDecorator (
168
120
decoration: widget.decoration.copyWith (
169
121
errorText: field.errorText,
170
122
),
171
123
child: Row (
124
+ key: ObjectKey (field.value),
172
125
children: [
173
- CountryPickerUtils .getDefaultFlagImage (_selectedDialogCountry ),
126
+ CountryPickerUtils .getDefaultFlagImage (field.value ),
174
127
SizedBox (
175
128
width: 10 ,
176
129
),
177
130
Expanded (
178
131
child: Text (
179
- "${_selectedDialogCountry . name }" ,
132
+ "${field . value ?. name ?? '' }" ,
180
133
style: widget.style,
181
134
),
182
135
),
@@ -187,4 +140,75 @@ class _FormBuilderCountryPickerState extends State<FormBuilderCountryPicker> {
187
140
},
188
141
);
189
142
}
143
+
144
+ void _openCupertinoCountryPicker (FormFieldState field) =>
145
+ showCupertinoModalPopup <void >(
146
+ context: context,
147
+ builder: (BuildContext context) {
148
+ return CountryPickerCupertino (
149
+ pickerSheetHeight: widget.cupertinoPickerSheetHeight ?? 300.0 ,
150
+ onValuePicked: (Country value) => field.didChange (value),
151
+ itemFilter: widget.countryFilterByIsoCode != null
152
+ ? (c) => widget.countryFilterByIsoCode.contains (c.isoCode)
153
+ : null ,
154
+ priorityList: widget.priorityListByIsoCode != null
155
+ ? List .generate (
156
+ widget.priorityListByIsoCode.length,
157
+ (index) => CountryPickerUtils .getCountryByIsoCode (
158
+ widget.priorityListByIsoCode[index]))
159
+ : null ,
160
+ );
161
+ },
162
+ );
163
+
164
+ void _openCountryPickerDialog (FormFieldState field) => showDialog (
165
+ context: context,
166
+ builder: (context) => Theme (
167
+ data: Theme .of (context).copyWith (
168
+ cursorColor: Theme .of (context).primaryColor,
169
+ primaryColor: widget.cursorColor ?? Theme .of (context).primaryColor,
170
+ ),
171
+ child: CountryPickerDialog (
172
+ titlePadding: widget.titlePadding ?? EdgeInsets .all (8.0 ),
173
+ searchCursorColor:
174
+ widget.cursorColor ?? Theme .of (context).primaryColor,
175
+ searchInputDecoration:
176
+ InputDecoration (hintText: widget.searchText ?? 'Search...' ),
177
+ isSearchable: widget.isSearchable ?? true ,
178
+ title: widget.dialogTitle ??
179
+ Text (
180
+ 'Select Your Country' ,
181
+ style: widget.dialogTextStyle ?? widget.style,
182
+ ),
183
+ onValuePicked: (Country value) => field.didChange (value),
184
+ itemFilter: widget.countryFilterByIsoCode != null
185
+ ? (c) => widget.countryFilterByIsoCode.contains (c.isoCode)
186
+ : null ,
187
+ priorityList: widget.priorityListByIsoCode != null
188
+ ? List .generate (
189
+ widget.priorityListByIsoCode.length,
190
+ (index) => CountryPickerUtils .getCountryByIsoCode (
191
+ widget.priorityListByIsoCode[index]))
192
+ : null ,
193
+ itemBuilder: _buildDialogItem,
194
+ ),
195
+ ),
196
+ );
197
+
198
+ Widget _buildDialogItem (Country country) {
199
+ return Container (
200
+ child: ListTile (
201
+ contentPadding: EdgeInsets .zero,
202
+ leading: CountryPickerUtils .getDefaultFlagImage (country),
203
+ title: Text ("${country .name }" ),
204
+ // visualDensity: VisualDensity.compact, //TODO: Re-enable after Flutter 1.17
205
+ ),
206
+ );
207
+ }
208
+
209
+ @override
210
+ void dispose () {
211
+ _formState? .unregisterFieldKey (widget.attribute);
212
+ super .dispose ();
213
+ }
190
214
}
0 commit comments