所以我设法解决了这个问题。
我的问题实际上应该分解为 3 个问题。
- 验证文本表单字段、单选按钮、所有自定义输入。
- 创建一个可以传递转换为 JSON 的新模型类。
- 从另一个小部件(Appbar)中的按钮提交表单。
为了解决第一个问题,我将 SurveyForm 中的所有内容都包装到了一个 Form 小部件中。这部分很简单,网上有很多教程。为了对自定义输入进行验证,我将输入包装在一个FormField 小部件中,并触发FormFieldState 的didChange 方法。这允许我使用方法callback 使用FormField 的validator 和onSaved 方法。下面是我的日期选择器工作代码。
class Q1<T> extends StatefulWidget {
final FormFieldValidator<DateTime> validator;
final FormFieldSetter<DateTime> onSaved;
const Q1({
Key key,
@required this.onSaved,
@required this.validator,
}) : assert(validator != null),
assert(onSaved != null),
super(
key: key,
);
@override
_Q1State createState() => _Q1State();
}
class _Q1State extends State<Q1> {
DateTime _completionDate;
@override
Widget build(BuildContext context) {
return FormField(
validator: (val) {
return widget.validator(val);
},
onSaved: (val) {
widget.onSaved(val);
},
builder: (FormFieldState<dynamic> field) {
return Row(
children: [
Expanded(
flex: 1,
child: Text('1. Completion Date'),
),
Expanded(
flex: 2,
child: Row(
children: [
Container(
padding: EdgeInsets.all(
SizeConfig().getProportionateScreenWidth(
kDatePickerIconTextBoxPadding),
),
decoration: BoxDecoration(
border: Border.all(
color: kDatePickerIconTextBoxBorderColor,
),
borderRadius: BorderRadius.all(Radius.circular(
SizeConfig().getProportionateScreenWidth(
kDatePickerIconTextBoxRadius),
) // <--- border radius here
),
),
child: Text(_completionDate == null
? 'Pick a date'
: DateFormat(kDateFormat).format(_completionDate)),
),
IconButton(
onPressed: () {
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2100),
).then((date) {
setState(() {
field.didChange(date);
_completionDate = date;
});
});
},
icon: FaIcon(FontAwesomeIcons.calendarAlt)),
],
),
),
],
);
},
);
}
}
我只是用
调用了这个小部件
Q1(
validator: (val) {
if (val == null) {
return 'Completion Date is missing';
}
return null;
},
onSaved: (value) {
setState(() {
widget.questionnaire.completion_date = DateFormat(kDateFormat).format(value);
});
},
),
为了解决第二个问题。我使用了json_serializable,该对象也可以在 HomeApp 和 SurveyForm 小部件之间传递,因此我不需要传递大约 50 多个变量。
对于第三个问题,我在 HomeApp 中发起final _formKey = GlobalKey<FormState>();,并将其传递给SurveyForm 小部件,并在Appbar 中使用onPressed 回调触发SurveyForm 中的验证/提交。
Bloc 将用于提交 JSON 和加载动画,但不限于此。
我是 Flutter 的新手(已经使用了一个月),如果有人有更好的解决方案,请告诉我。