我正在尝试在步进器的每个步骤中验证表单。我正在从地图上为步进创建列表。问题是,如果我为每一步添加表单,都会出错
多个小部件使用了相同的GlobalKey。
如何为每个表单动态创建新密钥
List<Step> stepList() {
List<Step> _steps = [];
list.forEach((k, v) => _steps.add(Step(
title: Text(k),
content: Column(
children: v.map<Widget>((child) {
return Form(key: _formKey, child: child);
}).toList(),
),
)));
return _steps;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stepper(
onStepContinue: next,
currentStep: current,
onStepCancel: cancel,
steps: stepList(),
),
);
}
这里是完整的复制粘贴代码...也尝试动态创建新密钥
class _MaterialScreenState extends State<MaterialScreen> {
int current = 0;
bool complete = false;
//final _formKey = GlobalKey<FormState>();
List<GlobalKey<FormState>> _getFormKeys() { //attempt to create list of Form keys for each step
List<GlobalKey<FormState>> l = [];
keyList().forEach((v) => l.add(GlobalKey<FormState>()));
return l;
}
goTo(int step) {
setState(() => current = step);
}
bool _validate() { // this method is called on null
final form = _getFormKeys()[current].currentState;
if (form.validate()) {
return true;
}
return false;
}
next() {
bool validated = _validate();
print(validated);
if (complete == false) {
if (current + 1 != list.length && validated) {
goTo(current + 1);
}
if (current + 1 == list.length) {
setState(() {
complete = true;
});
}
} else {
print('saved');
}
}
cancel() {
if (current > 0) {
goTo(current - 1);
}
}
List<String> keyList() {
List<String> l = [];
list.forEach((k, v) {
l.add(k);
});
return l;
}
Map<String, List<Widget>> list = {
'Step1': [
TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')
],
'Step2': [
TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')
],
'Step3': [TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')]
};
List<Step> stepList() {
List<Step> _steps = [];
list.forEach((k, v) => _steps.add(Step(
title: Text(k),
content: Column(
children: v.map<Widget>((child) {
return Form(
key: _getFormKeys()[keyList().indexOf(k)], child: child);
}).toList(),
),
)));
return _steps;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stepper(
onStepContinue: next,
currentStep: current,
onStepCancel: cancel,
steps: stepList(),
),
);
}
}
答案 0 :(得分:1)
感谢@pskink,问题得到了答案
这是完整的代码,如何验证步进机中的每个表单步骤
class MaterialScreen extends StatefulWidget {
@override
_MaterialScreenState createState() => _MaterialScreenState();
}
class _MaterialScreenState extends State<MaterialScreen> {
Map<String, List<Widget>> list = {
'Step1': [TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')],
'Step2': [TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')],
'Step3': [TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')],
};
Map steps;
@override
void initState() {
super.initState();
steps = list.map<GlobalKey, Step>(_makeStep);
}
MapEntry<GlobalKey, Step> _makeStep(k, v) {
var key = GlobalKey();
var step = Step(
title: Text(k),
content: Form(key: key, child: Column(children: v,),),
);
return MapEntry(key, step);
}
int current = 0;
bool complete = false;
goTo(int step) {
setState(() => current = step);
}
bool _validate() {
final form = steps.keys.elementAt(current).currentState;
return form.validate();
}
next() {
bool validated = _validate();
print(validated);
if (complete == false) {
if (current + 1 != list.length && validated) {
goTo(current + 1);
}
if (current + 1 == list.length) {
setState(() {
complete = true;
});
}
} else {
print('saved');
}
}
cancel() {
if (current > 0) {
goTo(current - 1);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stepper(
onStepContinue: next,
currentStep: current,
onStepCancel: cancel,
steps: steps.values.toList(),
),
);
}
}
答案 1 :(得分:1)
之所以不起作用,并且您的validate方法被调用为null的原因是因为每次调用它时,都在_getFormKeys()方法中创建了brad new GlobalKey。您要做的就是在initState中初始化globalKey列表,然后在进行操作时使用它们
class _MaterialScreenState extends State<MaterialScreen> {
int current = 0;
bool complete = false;
List<GlobalKey<FormState>> _formKeyList = []; //<- create variable for the list
Map<String, List<Widget>> list = {
'Step1': [
TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')
],
'Step2': [
TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')
],
'Step3': [TextFormField(validator: (s) => s.isNotEmpty ? null : 'Required')]
};
void initState() {
list.forEach((k, v) {
_formKeyList.add(GlobalKey<FormState>()); //<-- initialise it here
});
super.initState();
}
goTo(int step) {
setState(() => current = step);
}
bool _validate() {
// this method is called on null
final form = _formKeyList[current].currentState;
if (form.validate()) {
return true;
}
return false;
}
next() {
bool validated = _validate();
print(validated);
if (complete == false) {
if (current + 1 != list.length && validated) {
goTo(current + 1);
}
if (current + 1 == list.length) {
setState(() {
complete = true;
});
}
} else {
print('saved');
}
}
cancel() {
if (current > 0) {
goTo(current - 1);
}
}
List<String> keyList() {
List<String> l = [];
list.forEach((k, v) {
l.add(k);
});
return l;
}
List<Step> stepList() {
List<Step> _steps = [];
list.forEach((k, v) => _steps.add(Step(
title: Text(k),
content: Column(
children: v.map<Widget>((child) {
return Form(
key: _formKeyList[keyList().indexOf(k)], child: child);
}).toList(),
),
)));
return _steps;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stepper(
onStepContinue: next,
currentStep: current,
onStepCancel: cancel,
steps: stepList(),
),
);
}
}