在我的代码中,我验证电话号码。如果电话号码不正确-我会显示错误消息。但是,当用户开始编辑号码时,我想隐藏此错误消息。
我找到了currentState.reset()
的解决方案,但这似乎不是一个好的解决方案。我必须处理保存文本和光标位置的问题。而且我还有一个小神器。通常,当我按住退格键时,它将一一删除符号。如果在显示错误消息时执行此操作-错误消息消失并且仅删除一个符号。
有人知道这种情况的正确解决方案吗?
final TextEditingController controller = TextEditingController();
final RegExp _phoneRegex = RegExp(r"^\+{1}\d{10, 15}\$");
bool isError = false;
TextSelection currentPosition;
return Column(
children: <Widget>[
Form(
key: _textKey,
child: TextFormField(
controller: controller,
validator: (str) {
isError = true;
if (str.isEmpty) {
return err_empty_field;
} else if (!_phoneRegex.hasMatch(str)) {
return err_invalid_phone;
}
isError = false;
},
),
onChanged: () {
if (controller.selection.start < 0 &&
controller.text.length > 0) {
TextSelection position =
controller.text.length > currentPosition.start
? currentPosition
: TextSelection.fromPosition(
TextPosition(offset: controller.text.length));
controller.selection = position;
}
if (isError) {
isError = false;
currentPosition = controller.selection;
if (currentPosition.start > controller.text.length) {
currentPosition = TextSelection.fromPosition(
TextPosition(offset: controller.text.length));
}
String currentText = controller.text;
_textKey.currentState.reset();
controller.text = currentText;
controller.selection = currentPosition;
}
},
),
RaisedButton(
onPressed: () {
_textKey.currentState.validate();
},
child: Text(login),
)
],
);
答案 0 :(得分:10)
这是解决此问题的合适方法。
您实际上不需要使用onChanged
或引起副作用的任何技巧,我通过创建一个初始化为false
的类属性来解决了该问题:
bool _autovalidate = false;
表单小部件具有命名属性autovalidate
。您应该将前一个布尔值传递给它:
Form(
key: _textKey,
autovalidate: _autovalidate,
...
)
在提交按钮onPressed()
方法中,如果表单为_autovalidate
,则应将true
布尔值更新为invalid
,这将使表单自动验证每个onChanged
调用中的TextFormField:
RaisedButton(
onPressed: () {
if (_textKey.currentState.validate()) {
print('valid');
} else {
print('invalid');
setState(() => _autoValidate = true);
}
},
child: Text(login),
)
我希望它对某人有所帮助。
autovalidate
在v1.19.0之后被弃用。
而是使用autovalidateMode
:
Form(
autovalidateMode: AutovalidateMode.onUserInteraction`.
...
)
答案 1 :(得分:3)
这里的问题是errorText
由validator
的{{1}}字段自动管理。同时,简单的解决方案是手动处理TextFormField
。
步骤1:创建
errorText
初始化为_errorText
。该字段将包含需要显示的错误消息。null
初始化为_error
。如果有错误,则提交的字段为false
,否则为true
。第2步:
false
分配给_errorText
第3步(重要):
确保TextFormField
TextFormField
返回一个validator
值。
在此处处理验证并将正确的错误消息分配给null
。
相应地更新_errorText
状态。
第4步(重要):
_error
和_errorText
。开始编辑后,这将立即从字段中删除错误。第5步:
_error
中触发字段验证并管理您的代码流... onFieldSubmitted
答案 2 :(得分:2)
...
AutovalidateMode _autoValidate = AutovalidateMode.disabled;
Form(
key: _textKey,
autovalidateMode: _autovalidate,
...
)
RaisedButton(
onPressed: () {
if (_textKey.currentState.validate()) {
print('valid');
} else {
print('invalid');
setState(() => _autoValidate = AutovalidateMode.always);
}
},
child: Text("login"),
)
答案 3 :(得分:1)
我已经实现了以下两项功能:
1)编辑时隐藏错误消息
2)按下登录按钮时验证输入字段
注意:我已评论电话号码正则表达式并进行了验证 字符串长度<10位数以进行测试。
fn main() {
let mut s = String::from("hello world");
{
let word = first_word(&s);
}
s.clear();
}
答案 4 :(得分:1)
我找到了可行且更简单的方法
final _textKey = GlobalKey<FormState>();
final TextEditingController _controller = TextEditingController();
Widget _getPhoneInputForm() {
final RegExp _phoneRegex = RegExp(r"^\+{1}\d{10,17}");
bool isError = false;
bool isButtonPressed = false;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 36.0),
child: Form(
key: _textKey,
child: TextFormField(
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: hint_enter_phone,
contentPadding: EdgeInsets.all(24.0),
fillColor: Colors.blueGrey.withOpacity(0.3),
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(16.0)),
borderSide: BorderSide(color: Colors.blueGrey))),
controller: _controller,
validator: (str) {
if (!isButtonPressed) {
return null;
}
isError = true;
if (str.isEmpty) {
return err_empty_field;
} else if (!_phoneRegex.hasMatch(str)) {
return err_invalid_phone;
}
isError = false;
},
onFieldSubmitted: (str) {
if (_textKey.currentState.validate()) _phoneLogin();
},
),
onChanged: () {
isButtonPressed = false;
if (isError) {
_textKey.currentState.validate();
}
},
),
),
RaisedButton(
color: Colors.teal,
textColor: Colors.white,
onPressed: () {
isButtonPressed = true;
if (_textKey.currentState.validate()) _phoneLogin();
},
child: Text(login),
)
],
);
}
答案 5 :(得分:0)
这是一个例子,我认为没有必要执行onchange(),函数validate name可以完成工作...
String validateName(String value) {
String patttern = r'(^[a-zA-Z ]*$)';
RegExp regExp = new RegExp(patttern);
if (value.length == 0) {
return "Name is Required";
} else if (!regExp.hasMatch(value)) {
return "Name must be a-z and A-Z";
}
return null;
}
TextFormField(
controller: _lastname, validator: validateName ,
//initialValue: widget.contact.last_name,
decoration:
InputDecoration(labelText: 'Last name'),
),
void Save() {
if (_keyForm.currentState.validate()) {
// No any error in validation
_keyForm.currentState.save();
................
}