@@ -32,6 +32,7 @@ class _EditProductScreenState extends State<EditProductScreen> {
32
32
'imageUrl' : '' ,
33
33
};
34
34
bool _isInit = true ;
35
+ bool _isLoading = false ;
35
36
36
37
@override
37
38
void dispose () {
@@ -50,11 +51,25 @@ class _EditProductScreenState extends State<EditProductScreen> {
50
51
}
51
52
// save 메쇠드 사용시 각 TextFormFiled 의 onSave가 동작
52
53
_formKey.currentState.save ();
54
+ setState (() {
55
+ _isLoading = true ;
56
+ });
53
57
if (_editedProduct.id != null ) {
54
58
Provider .of <Products >(context, listen: false )
55
59
.updateProduct (_editedProduct.id, _editedProduct);
60
+ Navigator .of (context).pop ();
61
+ setState (() {
62
+ _isLoading = false ;
63
+ });
56
64
}
57
- Provider .of <Products >(context, listen: false ).addProduct (_editedProduct);
65
+ Provider .of <Products >(context, listen: false )
66
+ .addProduct (_editedProduct)
67
+ .then (((_) {
68
+ Navigator .of (context).pop ();
69
+ setState (() {
70
+ _isLoading = false ;
71
+ });
72
+ }));
58
73
}
59
74
60
75
@override
@@ -87,170 +102,174 @@ class _EditProductScreenState extends State<EditProductScreen> {
87
102
icon: Icon (Icons .save),
88
103
onPressed: () {
89
104
_saveForm ();
90
- Navigator .of (context).pop ();
91
105
}),
92
106
],
93
107
),
94
- body: Padding (
95
- padding: const EdgeInsets .all (16.0 ),
96
- child: Form (
97
- key: _formKey,
98
- child: ListView (
99
- children: < Widget > [
100
- TextFormField (
101
- initialValue: _initValue['title' ],
102
- decoration: InputDecoration (labelText: 'Title' ),
103
- textInputAction: TextInputAction .next,
104
- onFieldSubmitted: (_) {
105
- FocusScope .of (context).requestFocus (_priceFocusNode);
106
- },
107
- validator: (value) {
108
- if (value.isEmpty) {
109
- return 'Please provide a value' ;
110
- }
111
- return null ;
112
- },
113
- onSaved: (value) {
114
- _editedProduct = Product (
115
- title: value,
116
- price: _editedProduct.price,
117
- description: _editedProduct.description,
118
- imageUrl: _editedProduct.imageUrl,
119
- id: _editedProduct.id,
120
- isFavorite: _editedProduct.isFavorite,
121
- );
122
- },
123
- ),
124
- TextFormField (
125
- initialValue: _initValue['price' ],
126
- decoration: InputDecoration (labelText: 'Price' ),
127
- textInputAction: TextInputAction .next,
128
- keyboardType: TextInputType .number,
129
- focusNode: _priceFocusNode,
130
- onFieldSubmitted: (_) {
131
- FocusScope .of (context).requestFocus (_descriptionFocusNode);
132
- },
133
- validator: (value) {
134
- if (value.isEmpty) {
135
- return 'Please provide a price' ;
136
- }
137
- if (double .tryParse (value) == null ) {
138
- return 'Please enter a valid number' ;
139
- }
140
- if (double .parse (value) <= 0 ) {
141
- return 'Please enater a number greater than zero' ;
142
- }
143
- return null ;
144
- },
145
- onSaved: (value) {
146
- _editedProduct = Product (
147
- title: _editedProduct.title,
148
- price: double .parse (value),
149
- description: _editedProduct.description,
150
- imageUrl: _editedProduct.imageUrl,
151
- id: _editedProduct.id,
152
- isFavorite: _editedProduct.isFavorite,
153
- );
154
- },
155
- ),
156
- TextFormField (
157
- initialValue: _initValue['description' ],
158
- decoration: InputDecoration (labelText: 'Description' ),
159
- maxLines: 3 ,
160
- textInputAction: TextInputAction .next,
161
- keyboardType: TextInputType .multiline,
162
- focusNode: _descriptionFocusNode,
163
- onFieldSubmitted: (_) {
164
- FocusScope .of (context).requestFocus (_imageUrlFocusNode);
165
- },
166
- validator: (value) {
167
- if (value.isEmpty) {
168
- return 'Please provide a description' ;
169
- }
170
- if (value.length < 10 ) {
171
- return 'Should be at least 10 characters long' ;
172
- }
173
- return null ;
174
- },
175
- onSaved: (value) {
176
- _editedProduct = Product (
177
- title: _editedProduct.title,
178
- price: _editedProduct.price,
179
- description: value,
180
- imageUrl: _editedProduct.imageUrl,
181
- id: _editedProduct.id,
182
- isFavorite: _editedProduct.isFavorite,
183
- );
184
- },
185
- ),
186
- Row (
187
- crossAxisAlignment: CrossAxisAlignment .end,
188
- children: < Widget > [
189
- Container (
190
- width: 100 ,
191
- height: 100 ,
192
- margin: EdgeInsets .only (top: 8 , right: 10 ),
193
- decoration: BoxDecoration (
194
- border: Border .all (
195
- width: 1 ,
196
- color: Colors .grey,
197
- ),
108
+ body: _isLoading
109
+ ? Center (
110
+ child: CircularProgressIndicator (),
111
+ )
112
+ : Padding (
113
+ padding: const EdgeInsets .all (16.0 ),
114
+ child: Form (
115
+ key: _formKey,
116
+ child: ListView (
117
+ children: < Widget > [
118
+ TextFormField (
119
+ initialValue: _initValue['title' ],
120
+ decoration: InputDecoration (labelText: 'Title' ),
121
+ textInputAction: TextInputAction .next,
122
+ onFieldSubmitted: (_) {
123
+ FocusScope .of (context).requestFocus (_priceFocusNode);
124
+ },
125
+ validator: (value) {
126
+ if (value.isEmpty) {
127
+ return 'Please provide a value' ;
128
+ }
129
+ return null ;
130
+ },
131
+ onSaved: (value) {
132
+ _editedProduct = Product (
133
+ title: value,
134
+ price: _editedProduct.price,
135
+ description: _editedProduct.description,
136
+ imageUrl: _editedProduct.imageUrl,
137
+ id: _editedProduct.id,
138
+ isFavorite: _editedProduct.isFavorite,
139
+ );
140
+ },
198
141
),
199
- child: _imageUrlController.text.isEmpty
200
- ? Text (
201
- 'Enter a URL' ,
202
- textAlign: TextAlign .center,
203
- )
204
- : FittedBox (
205
- child: Image .network (
206
- _imageUrlController.text,
207
- fit: BoxFit .cover,
208
- ),
209
- ),
210
- ),
211
- Expanded (
212
- child: TextFormField (
213
- decoration: InputDecoration (labelText: 'Image URL' ),
214
- keyboardType: TextInputType .url,
215
- textInputAction: TextInputAction .done,
216
- controller: _imageUrlController,
217
- focusNode: _imageUrlFocusNode,
218
- onEditingComplete: () {
219
- setState (() {});
142
+ TextFormField (
143
+ initialValue: _initValue['price' ],
144
+ decoration: InputDecoration (labelText: 'Price' ),
145
+ textInputAction: TextInputAction .next,
146
+ keyboardType: TextInputType .number,
147
+ focusNode: _priceFocusNode,
148
+ onFieldSubmitted: (_) {
149
+ FocusScope .of (context)
150
+ .requestFocus (_descriptionFocusNode);
220
151
},
221
152
validator: (value) {
222
153
if (value.isEmpty) {
223
- return 'Please enter an image URL ' ;
154
+ return 'Please provide a price ' ;
224
155
}
225
- if (! value.startsWith ('http' ) &&
226
- ! value.startsWith ('https' )) {
227
- return 'Please enter a valid URL' ;
156
+ if (double .tryParse (value) == null ) {
157
+ return 'Please enter a valid number' ;
228
158
}
229
- if (! value.endsWith ('.png' ) &&
230
- ! value.endsWith ('.jpg' ) &&
231
- ! value.endsWith ('.jpeg' )) {
232
- return 'Please enter a valid image URL' ;
159
+ if (double .parse (value) <= 0 ) {
160
+ return 'Please enater a number greater than zero' ;
233
161
}
234
162
return null ;
235
163
},
236
164
onSaved: (value) {
237
165
_editedProduct = Product (
238
166
title: _editedProduct.title,
239
- price: _editedProduct.price ,
167
+ price: double . parse (value) ,
240
168
description: _editedProduct.description,
241
- imageUrl: value ,
169
+ imageUrl: _editedProduct.imageUrl ,
242
170
id: _editedProduct.id,
243
171
isFavorite: _editedProduct.isFavorite,
244
172
);
245
173
},
246
174
),
247
- )
248
- ],
249
- )
250
- ],
251
- ),
252
- ),
253
- ),
175
+ TextFormField (
176
+ initialValue: _initValue['description' ],
177
+ decoration: InputDecoration (labelText: 'Description' ),
178
+ maxLines: 3 ,
179
+ textInputAction: TextInputAction .next,
180
+ keyboardType: TextInputType .multiline,
181
+ focusNode: _descriptionFocusNode,
182
+ onFieldSubmitted: (_) {
183
+ FocusScope .of (context).requestFocus (_imageUrlFocusNode);
184
+ },
185
+ validator: (value) {
186
+ if (value.isEmpty) {
187
+ return 'Please provide a description' ;
188
+ }
189
+ if (value.length < 10 ) {
190
+ return 'Should be at least 10 characters long' ;
191
+ }
192
+ return null ;
193
+ },
194
+ onSaved: (value) {
195
+ _editedProduct = Product (
196
+ title: _editedProduct.title,
197
+ price: _editedProduct.price,
198
+ description: value,
199
+ imageUrl: _editedProduct.imageUrl,
200
+ id: _editedProduct.id,
201
+ isFavorite: _editedProduct.isFavorite,
202
+ );
203
+ },
204
+ ),
205
+ Row (
206
+ crossAxisAlignment: CrossAxisAlignment .end,
207
+ children: < Widget > [
208
+ Container (
209
+ width: 100 ,
210
+ height: 100 ,
211
+ margin: EdgeInsets .only (top: 8 , right: 10 ),
212
+ decoration: BoxDecoration (
213
+ border: Border .all (
214
+ width: 1 ,
215
+ color: Colors .grey,
216
+ ),
217
+ ),
218
+ child: _imageUrlController.text.isEmpty
219
+ ? Text (
220
+ 'Enter a URL' ,
221
+ textAlign: TextAlign .center,
222
+ )
223
+ : FittedBox (
224
+ child: Image .network (
225
+ _imageUrlController.text,
226
+ fit: BoxFit .cover,
227
+ ),
228
+ ),
229
+ ),
230
+ Expanded (
231
+ child: TextFormField (
232
+ decoration: InputDecoration (labelText: 'Image URL' ),
233
+ keyboardType: TextInputType .url,
234
+ textInputAction: TextInputAction .done,
235
+ controller: _imageUrlController,
236
+ focusNode: _imageUrlFocusNode,
237
+ onEditingComplete: () {
238
+ setState (() {});
239
+ },
240
+ validator: (value) {
241
+ if (value.isEmpty) {
242
+ return 'Please enter an image URL' ;
243
+ }
244
+ if (! value.startsWith ('http' ) &&
245
+ ! value.startsWith ('https' )) {
246
+ return 'Please enter a valid URL' ;
247
+ }
248
+ if (! value.endsWith ('.png' ) &&
249
+ ! value.endsWith ('.jpg' ) &&
250
+ ! value.endsWith ('.jpeg' )) {
251
+ return 'Please enter a valid image URL' ;
252
+ }
253
+ return null ;
254
+ },
255
+ onSaved: (value) {
256
+ _editedProduct = Product (
257
+ title: _editedProduct.title,
258
+ price: _editedProduct.price,
259
+ description: _editedProduct.description,
260
+ imageUrl: value,
261
+ id: _editedProduct.id,
262
+ isFavorite: _editedProduct.isFavorite,
263
+ );
264
+ },
265
+ ),
266
+ )
267
+ ],
268
+ )
269
+ ],
270
+ ),
271
+ ),
272
+ ),
254
273
);
255
274
}
256
275
}
0 commit comments