Я создал Form
Виджет в этой форме есть несколько TextFormFeild
, которые я создал пользовательские BoxFeild
.Я столкнулся с проблемой, связанной с auto-validation
из виджета формы.Невозможно проверить совпадение пароля в поле подтверждения пароля BoxFeild
Должен ли я validate password
сопоставить после того, как formKeyData сохранен в current state
?
Возникает проблема при передаче ключа в конструктор BoxFeild
.Показывает несколько виджетов, использующих один и тот же глобальный ключ.
Мне нужно добавить глобальный ключ FormFeild для сравнения _password
и _confirmPassword
.
class _PageSignUpState extends State<PageSignUp> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
var passKey = GlobalKey<FormFieldState>();
bool _autoValidate = false;
String _name, _email, _phoneNo, _password, _confirmPassoword;
bool isLoading = false;
final _passwordController = TextEditingController();
final _confirmPassController = TextEditingController();
double width,height;
@override
Widget build(BuildContext context) {
width = MediaQuery.of(context).size.width;
height = MediaQuery.of(context).size.height;
return Scaffold(
backgroundColor: Colors.white,
body: Container(
color: Colors.grey.shade200,
child: Center(
child: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Form(
key: _formKey,
autovalidate: _autoValidate,
child: Column(
children: <Widget>[
_nameWidget(),
_emailWidget(),
_passwordWidget(),
_confirmPassWidget(),
SizedBox(height: height/25),
_signUpButtonWidget()
],
)),
],
),
),
),
),
),
);
}
Container _signUpButtonWidget() {
return Container(
padding: EdgeInsets.symmetric(vertical: height / 40, horizontal: width / 15),
width: double.infinity,
child: RaisedButton(
padding: EdgeInsets.all(12.0),
child: Text(
"Sign Up",
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
color: Colors.blue,
onPressed: () {
setLoading(true);
_validateInputs();
},
),
);
}
BoxFeild _confirmPassWidget() {
return BoxFeild(
hintText: "Confirm Password",
lableText: "Confirm Password",
obscureText: true,
icon: Icons.lock_outline,
validator: validatePasswordMatching,
onSaved: (String val) {
_confirmPassoword = val;
},
);
}
BoxFeild _passwordWidget() {
return BoxFeild(
key: passKey,
hintText: "Enter Password",
lableText: "Password",
obscureText: true,
icon: Icons.lock_outline,
controller: _passwordController,
validator: validatePassword,
onSaved: (String val) {
_password = val;
},
);
}
BoxFeild _emailWidget() {
return BoxFeild(
hintText: "Enter Email",
lableText: "Email",
keyboardType: TextInputType.emailAddress,
icon: Icons.email,
validator: validateEmail,
onSaved: (String val) {
_email = val;
},
);
}
BoxFeild _nameWidget() {
return BoxFeild(
hintText: "Enter Name",
lableText: "Name",
icon: Icons.person,
validator: validateName,
onSaved: (String val) {
_name = val;
},
);
}
String validateName(String value) {
String patttern = r'(^[a-zA-Z ]*$)';
RegExp regExp = 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;
}
String validateEmail(String value) {
RegExp regExp = RegExp(Constants.PATTERN_EMAIL, caseSensitive: false);
if (value.length == 0) {
return "Email is Required";
} else if (!regExp.hasMatch(value)) {
return "Enter valid email address.";
}
return null;
}
String validatePassword(String value) {
if (value.length == 0) {
return "Password is Required";
} else if (value.length < 6) {
return "Password Should be more than 6.";
}
return null;
}
String validatePasswordMatching(String value) {
var password = passKey.currentState.value;
if (value.length == 0) {
return "Password is Required";
} else if (value != password) {
return 'Password is not matching';
}
return null;
}
void _validateInputs() {
if (_formKey.currentState.validate()) {
//If all data are correct then save data to out variables
//Make a REST Api Call with success Go to Login Page after User Created.
_formKey.currentState.save();
setLoading(true);
Utils.checkConnection().then((connectionResult) {
if (connectionResult) {
} else {
setLoading(false);
Utils.showAlert(context, "Flutter",
"Internet is not connected. Please check internet connection.",
() {
Navigator.pop(context);
}, true);
}
});
}
} else {
// If all data are not valid then start auto validation.
setState(() {
_autoValidate = true;
});
}
}
}
BoxFeild.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class BoxFeild extends StatefulWidget {
final TextEditingController controller;
final FocusNode focusNode;
final TextInputType keyboardType;
final TextInputAction textInputAction;
final TextCapitalization textCapitalization;
final TextStyle style;
final TextAlign textAlign;
final bool autofocus;
final bool obscureText;
final bool autocorrect;
final int maxLines;
final Key key;
final int maxLength;
final bool maxLengthEnforced;
final ValueChanged<String> onChanged;
final VoidCallback onEditingComplete;
final ValueChanged<String> onSubmitted;
final List<TextInputFormatter> inputFormatters;
final bool enabled;
final IconData icon;
final String hintText;
final String lableText;
final double cursorWidth;
final Radius cursorRadius;
final Color cursorColor;
final Color defaultBorderColor;
final Brightness keyboardAppearance;
final EdgeInsets scrollPadding;
final FormFieldValidator<String> validator;
final ValueChanged<String> onFieldSubmitted;
final FormFieldSetter<String> onSaved;
const BoxFeild({
this.key,
this.controller,
this.focusNode,
TextInputType keyboardType,
this.textInputAction,
this.textCapitalization = TextCapitalization.none,
this.style,
this.icon,
this.textAlign = TextAlign.start,
this.autofocus = false,
this.obscureText = false,
this.autocorrect = true,
this.maxLines = 1,
this.maxLength,
this.onSaved,
this.hintText,
this.lableText,
this.maxLengthEnforced = true,
this.onChanged,
this.defaultBorderColor,
this.onEditingComplete,
this.onSubmitted,
this.inputFormatters,
this.enabled,
this.cursorWidth = 2.0,
this.cursorRadius,
this.cursorColor,
this.keyboardAppearance,
this.scrollPadding,
this.validator,
this.onFieldSubmitted,
}) : assert(textAlign != null),
assert(autofocus != null),
assert(obscureText != null),
assert(autocorrect != null),
assert(maxLengthEnforced != null),
assert(maxLines == null || maxLines > 0),
assert(maxLength == null || maxLength > 0),
keyboardType = keyboardType ??
(maxLines == 1 ? TextInputType.text : TextInputType.multiline);
@override
_BoxFeildState createState() => _BoxFeildState();
}
class _BoxFeildState extends State<BoxFeild> {
double width;
double height;
Color focusBorderColor = Colors.grey.shade400;
FocusNode _focusNode = FocusNode();
ValueChanged<Colors> focusColorChange;
@override
void dispose() {
super.dispose();
_focusNode.dispose();
}
@override
Widget build(BuildContext context) {
width = MediaQuery.of(context).size.width;
height = MediaQuery.of(context).size.height;
return Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: width / 30,
),
Expanded(
child: Container(
margin: EdgeInsets.only(top: height / 400, bottom: height / 400, left: width / 50, right: width / 50),
padding: EdgeInsets.all(height / 100),
alignment: Alignment.center,
height: height / 14,
decoration: BoxDecoration(
color: Colors.grey.shade100,
border: Border.all(color: focusBorderColor, width: 1.0),
borderRadius: BorderRadius.circular(8.0)),
child: TextFormField(
key: this.widget.key,
obscureText: this.widget.obscureText,
onSaved: this.widget.onSaved,
validator: this.widget.validator,
onFieldSubmitted: this.widget.onFieldSubmitted,
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(
this.widget.icon,
size: height/34,
),
hintText: this.widget.hintText),
),
)),
],
),
padding: EdgeInsets.only(bottom : height / 58),
margin: EdgeInsets.only(
top: height / 50, right: width / 20, left: width / 30),
);
}
}
Теперь Если я использую другой Контейнер для поля пароля, то он работает.И если я передаю ключ и контроллер в boxfeild, тогда его шоу
несколько виджетов использовали один и тот же глобальный ключ
Container _passwordWidget() {
return Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.center,
height: 52.0,
decoration: BoxDecoration(
color: Colors.grey.shade100,
border: Border.all(color: Colors.transparent, width: 0.0),
borderRadius: BorderRadius.circular(12.0)),
child: TextFormField(
key: passKey,
obscureText: true,
validator: validatePassword,
onSaved: (String val) {
_password = val;
},
keyboardType: TextInputType.number,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
),
decoration:
InputDecoration.collapsed(hintText: "Password"),
),
);
}