forms - Flutter 表单同时显示所有字段的错误。如何让它显示一个字段的验证消息?
问题描述
下面是我的代码。我有 6 个字段。所有这些都同时显示错误。即使在我提交表格之后。一旦它被清除。它将显示验证消息,因为字段不能为空 /Name 是必需的。我如何一次验证每个字段。我不希望所有字段都显示验证消息,如下图所示。
import 'package:flutter/material.dart';
class FormScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return FormScreenState();
}
}
class FormScreenState extends State<FormScreen> {
String _name;
String _email;
String _password;
String _url;
String _phoneNumber;
String _calories;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget _buildName() {
return TextFormField(
decoration: InputDecoration(labelText: 'Name'),
maxLength: 10,
validator: (String value) {
if (value.isEmpty) {
return 'Name is Required';
}
return null;
},
onSaved: (String value) {
_name = value;
},
);
}
Widget _buildEmail() {
return TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (String value) {
if (value.isEmpty) {
return 'Email is Required';
}
if (!RegExp(
r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
.hasMatch(value)) {
return 'Please enter a valid email Address';
}
return null;
},
onSaved: (String value) {
_email = value;
},
);
}
Widget _buildPassword() {
return TextFormField(
decoration: InputDecoration(labelText: 'Password'),
keyboardType: TextInputType.visiblePassword,
validator: (String value) {
if (value.isEmpty) {
return 'Password is Required';
}
return null;
},
onSaved: (String value) {
_password = value;
},
);
}
Widget _builURL() {
return TextFormField(
decoration: InputDecoration(labelText: 'Url'),
keyboardType: TextInputType.url,
validator: (String value) {
if (value.isEmpty) {
return 'URL is Required';
}
return null;
},
onSaved: (String value) {
_url = value;
},
);
}
Widget _buildPhoneNumber() {
return TextFormField(
decoration: InputDecoration(labelText: 'Phone number'),
keyboardType: TextInputType.phone,
validator: (String value) {
if (value.isEmpty) {
return 'Phone number is Required';
}
return null;
},
onSaved: (String value) {
_url = value;
},
);
}
Widget _buildCalories() {
return TextFormField(
decoration: InputDecoration(labelText: 'Calories'),
keyboardType: TextInputType.number,
validator: (String value) {
int calories = int.tryParse(value);
if (calories == null || calories <= 0) {
return 'Calories must be greater than 0';
}
return null;
},
onSaved: (String value) {
_calories = value;
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Form Demo")),
body: Container(
margin: EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildName(),
_buildEmail(),
_buildPassword(),
_builURL(),
_buildPhoneNumber(),
_buildCalories(),
SizedBox(height: 100),
RaisedButton(
child: Text(
'Submit',
style: TextStyle(color: Colors.blue, fontSize: 16),
),
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
print(_name);
print(_email);
print(_phoneNumber);
print(_url);
print(_password);
print(_calories);
//Send to API
},
)
],
),
),
),
);
}
}
解决方案
FocusNode
按autovalidateMode: tempFocusNode.hasFocus? AutovalidateMode.always:AutovalidateMode.disabled
如下方式使用 ,TextFormField
这将解决您的问题。
import 'package:flutter/material.dart';
class FormScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return FormScreenState();
}
}
class FormScreenState extends State<FormScreen> {
String _name;
String _email;
String _password;
String _url;
String _phoneNumber;
String _calories;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
//在这里创建焦点节点
FocusNode nameFocusNode= FocusNode();
FocusNode emailFocusNode= FocusNode();
Widget _buildName() {
return TextFormField(
focusNode:nameFocusNode,
autovalidateMode: nameFocusNode.hasFocus
? AutovalidateMode.always
: AutovalidateMode.disabled,
decoration: InputDecoration(labelText: 'Name'),
maxLength: 10,
validator: (String value) {
if (value.isEmpty) {
return 'Name is Required';
}
return null;
},
onSaved: (String value) {
_name = value;
},
);
}
............
Widget _buildEmail() {
return TextFormField(
focusNode:emailFocusNode,
autovalidateMode: nameFocusNode.hasFocus
? AutovalidateMode.always
: AutovalidateMode.disabled,
decoration: InputDecoration(labelText: 'Email'),
validator: (String value) {
if (value.isEmpty) {
return 'Email is Required';
}
if (!RegExp(
r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
.hasMatch(value)) {
return 'Please enter a valid email Address';
}
return null;
},
onSaved: (String value) {
_email = value;
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Form Demo")),
body: Container(
margin: EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildName(),
_buildEmail(),
_buildPassword(),
_builURL(),
_buildPhoneNumber(),
_buildCalories(),
SizedBox(height: 100),
RaisedButton(
child: Text(
'Submit',
style: TextStyle(color: Colors.blue, fontSize: 16),
),
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
print(_name);
print(_email);
print(_phoneNumber);
print(_url);
print(_password);
print(_calories);
//Send to API
},
)
],
),
),
),
);
}
}
推荐阅读
- c - 函数'write'的隐式声明;您指的是 'fwrite' 吗?
- sql - 查找连续事件之间的最大天数
- terratest - 需要有关使用 terratest 完成管道后如何测试 Vertex AI 端点的信息
- batch-file - 按顺序将多个 .ts 文件批量连接到单个文件
- python - 我可以使用字典来跟踪 Python 中的对象吗?
- pine-script - 计算锯齿线的斜率/导数值
- asp.net-core - Octopus:appsettings.json 变量替换 3 级层次结构
- javascript - 如何将 Python 程序添加到 Web 项目中?
- postgresql - TypeORM中的Postgres OVERLAPS日期函数
- python - 在熊猫中像树方法一样迭代