因此对于我的注册屏幕,我必须填写两个TextFormField
用户:电子邮件和密码。因为我使用相同的样式,所以我想将TextFormField
重构为单独的小部件。在主窗口小部件中,当用户按下“注册”按钮时,我要验证所有三个字段。我已经用GlobalKey尝试过,但是收到错误消息“多个小部件使用了相同的GlobalKey。”
这是我的注册屏幕代码:
class RegistrationScreen extends StatefulWidget {
@override
_RegistrationScreenState createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
String email;
String password;
final formKey = GlobalKey<FormState>();
void handleRegisterEmail(){
if (formKey.currentState.validate()){
print('Handling Register');
}
}
void handleEmailChanged(String value) {
setState(() {
email = value;
});
}
void handlePasswordChanged(String value) {
setState(() {
password = value;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
AuthTextField(
key: formKey,
type: 'Email',
onChanged: handleEmailChanged,
),
AuthTextField(
key: formKey
type: 'Password',
onChanged: handlePasswordChanged,
),
AuthButton(
text: 'Register',
onPressed: handleRegisterEmail,
),
]
),
);
}
}
这是AuthTextField
的代码:
class AuthTextField extends StatefulWidget {
final String emailOrPassword;
final Function onChanged;
final GlobalKey<FormState> key; //Here passing the key
AuthTextField({this.onChanged, this.emailOrPassword, this.key})
: super(key: key);
@override
_AuthTextFieldState createState() => _AuthTextFieldState();
}
class _AuthTextFieldState extends State<AuthTextField> {
String validateForm(String value) { //two different validators
if (widget.emailOrPassword == 'Email') {
validateFormEmail(value);
} else {
validateFormPassword(value);
}
}
String validateFormEmail(String value) {
if (!RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(value)) {
return 'Please enter a valid email address';
}
return null;
}
String validateFormPassword(String value) {
if (value.length < 6) {
return 'Password must be at least 6 characters.';
}
return null;
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
key: widget.key, //Passing the key
validator: validateForm,
keyboardType: (widget.emailOrPassword == 'Email')
? TextInputType.emailAddress
: TextInputType.text,
onChanged: widget.onChanged,
//plus some more styling
),
),
);
}
}
正如我所说,我得到了错误消息。有什么建议如何解决这个问题?我尝试了很多不同的方法(例如,将RegistrationScreen中的列包装为表单,并将密钥仅传递给该表单),但是没有任何效果。
答案 0 :(得分:0)
这里的问题是您正在设置 key
的 AuthTextField
,而不是将其作为单独的字段存储在对象中。这是将其设置为 AuthTextField
和 Form
对象的键。
这是您想要做的:
class AuthTextField extends StatefulWidget {
final String emailOrPassword;
final Function onChanged;
final GlobalKey<FormState> formKey; //Here passing the key
AuthTextField({Key key, this.onChanged, this.emailOrPassword, this.formKey})
: super(key: key);
@override
_AuthTextFieldState createState() => _AuthTextFieldState();
}
class _AuthTextFieldState extends State<AuthTextField> {
String validateForm(String value) { //two different validators
if (widget.emailOrPassword == 'Email') {
validateFormEmail(value);
} else {
validateFormPassword(value);
}
}
String validateFormEmail(String value) {
if (!RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(value)) {
return 'Please enter a valid email address';
}
return null;
}
String validateFormPassword(String value) {
if (value.length < 6) {
return 'Password must be at least 6 characters.';
}
return null;
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
//key: widget.key, //Don't pass the key to the TextFormField only the form
validator: validateForm,
keyboardType: (widget.emailOrPassword == 'Email')
? TextInputType.emailAddress
: TextInputType.text,
onChanged: widget.onChanged,
//plus some more styling
),
),
);
}
}
然后您需要将您的小部件包装在一个 Form
小部件中:
class RegistrationScreen extends StatefulWidget {
@override
_RegistrationScreenState createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
String email;
String password;
final formKey = GlobalKey<FormState>();
void handleRegisterEmail(){
if (formKey.currentState.validate()){
print('Handling Register');
}
}
void handleEmailChanged(String value) {
setState(() {
email = value;
});
}
void handlePasswordChanged(String value) {
setState(() {
password = value;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Form(
key: formKey, //Wrap your column in this form widget and set the key
child: Column(
children: <Widget>[
AuthTextField(
key: formKey,
type: 'Email',
onChanged: handleEmailChanged,
),
AuthTextField(
key: formKey
type: 'Password',
onChanged: handlePasswordChanged,
),
AuthButton(
text: 'Register',
onPressed: handleRegisterEmail,
),
]
),
),
);
}
}