我目前正在动态创建自定义表单小部件 (Row),并且想知道验证每个表单的最佳方法是什么。通过尝试使用全局 FormState 键,没有任何作用,因为每个表单实例都共享该键(我假设)。
这会产生一些问题,例如键盘在专注于文本字段时立即退出。
想知道是否有人对此有解决方案或可以为我指明正确的方向。谢谢!
根小部件:
class ExerciseTable extends ConsumerWidget {
final Exercise exercise;
ExerciseTable({@required this.exercise});
@override
Widget build(BuildContext context, ScopedReader watch) {
final _exerciseTableController = watch(exerciseTableControllerProvider);
/*
* Logic of where I build the form rows dynamically
*/
List<Widget> _buildFormRows() {
List<Widget> rows = [];
int sets = int.parse(exercise.sets);
for (int i = 1; i < sets; i++) {
rows.add(
_BuildExerciseRow(
set: i.toString(),
),
);
}
return rows;
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
exercise.exerciseName,
style: Theme.of(context).textTheme.headline6,
),
const SizedBox(height: 8),
YoutubePlayerTile(
url: exercise.exerciseURL,
),
const SizedBox(height: 8),
_BuildRowHeader(),
Column(children: _buildFormRows())
],
);
}
}
单个表单行小部件:
/**
* * Form Rows
*/
class _BuildExerciseRow extends StatelessWidget {
final String set;
final _formKey = GlobalKey<FormState>();
final _kgTextEditingController = TextEditingController();
final _repsTextEditingController = TextEditingController();
_BuildExerciseRow({this.set});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 5),
child: Form(
key: _formKey,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Text(set),
const SizedBox(width: 15),
Text("-"),
const SizedBox(width: 15),
_BuildInputTextField(
controller: _kgTextEditingController,
validator: (value) {
if (value.isEmpty) {
return "Please enter some text";
} else
return "";
}),
// const SizedBox(width: 15),
_BuildInputTextField(
controller: _repsTextEditingController,
),
TickBox(onTap: () => _formKey.currentState.validate())
],
),
),
);
}
}
class _BuildInputTextField extends StatelessWidget {
// final int keyValue;
final String Function(String) validator;
final TextEditingController controller;
_BuildInputTextField({this.validator, @required this.controller});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 2),
height: 39,
width: 80,
child: TextFormField(
validator: validator,
inputFormatters: [
LengthLimitingTextInputFormatter(6),
],
controller: controller,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(bottom: 5, left: 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(width: 1),
),
),
onChanged: (value) => {}),
);
}
}
自定义 TextFormField 小部件:
class _BuildInputTextField extends StatelessWidget {
// final int keyValue;
final String Function(String) validator;
final TextEditingController controller;
_BuildInputTextField({this.validator, @required this.controller});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 2),
height: 39,
width: 80,
child: TextFormField(
validator: validator,
inputFormatters: [
LengthLimitingTextInputFormatter(6),
],
controller: controller,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(bottom: 5, left: 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(width: 1),
),
),
onChanged: (value) => {}),
);
}
}
答案 0 :(得分:0)
尝试将您的 validator
回调更改为
validator: (value) {
if (value.isEmpty) {
return "Please enter some text";
} else
return null;
}),
答案 1 :(得分:0)
已修复!
太简单了,我忘了把 _BuildExerciseRow
转换成 Stateful Widget。 (就我而言,是 Riverpod 的 Consumer Widget,它扩展了 StatefulWidget)。