flutter - 在一个页面视图中管理多个表单验证,其中一个按下
问题描述
按下回调按钮时,我必须同时提交 4 个表单。但是,当按下此按钮时,使用 onpressed 调用的函数必须验证所有要求都在 textformfield 的字段验证中执行。我只使用一个 formkey 并使用 formkey.validate 来验证要求是否被接受,但它不起作用,我不知道如何以不同的方式尝试。
class CreateAccountPage extends StatefulWidget {
CreateAccountPage({Key? key}) : super(key: key);
@override
_CreateAccountPageState createState() => _CreateAccountPageState();
}
class _CreateAccountPageState
extends ModularState<CreateAccountPage, CreateAccountController> {
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool? policy;
int currentPage = 0;
@override
void initState() {
super.initState();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
//physics: NeverScrollableScrollPhysics(),
controller: controller.pageViewController,
onPageChanged: (index) {
currentPage = index;
},
children: [
SafeArea(
child: Scaffold(
backgroundColor: AppColors.background,
body: SingleChildScrollView(
child: Stack(
children: <Widget>[
Positioned(
top: 74,
left: 48,
child: Image.asset(
'assets/images/logo_budget.png',
height: 53.85,
width: 100,
),
),
Positioned(
top: 144,
left: 48,
child: SizedBox(
width: 255.0,
height: 118.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Bem-Vindo!',
style: TextStyles.h3HeadCreateAccount,
),
Text(
"Por favor insira seus dados nos campos abaixo.",
style: TextStyles.h6HeadCreateAccount,
)
],
),
),
),
Container(
padding: EdgeInsets.only(top: 419, left: 48, right: 48),
child: Form(
key: formKey[0],
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: AppTextFormFieldWidget(
controller: controller.nameCreate,
hintText: 'Nome',
labelText: 'Nome',
//validator: (value) =>
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: AppTextFormFieldWidget(
controller: controller.emailCreate,
labelText: 'E-Mail',
hintText: 'E-Mail',
validator: (value) => InputValidators()
.emailValidator(value ?? ""),
),
),
],
),
),
),
],
),
),
),
),
SafeArea(
child: Scaffold(
backgroundColor: AppColors.background,
body: SingleChildScrollView(
child: Stack(
children: <Widget>[
Positioned(
top: 74,
left: 48,
child: Image.asset(
'assets/images/logo_budget.png',
height: 53.85,
width: 100,
),
),
Positioned(
top: 144,
left: 48,
child: SizedBox(
width: 255.0,
height: 86.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Bem-Vindo!',
style: TextStyles.h3HeadCreateAccount,
),
Text(
"Mais alguns dados.",
style: TextStyles.h6HeadCreateAccount,
)
],
),
),
),
Container(
padding: EdgeInsets.only(top: 419, left: 48, right: 48),
child: Form(
key: _formKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: AppTextFormFieldWidget(
controller: controller.telefoneCreate,
keyboardType: TextInputType.phone,
hintText: 'Telefone',
labelText: 'Telefone',
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
TelefoneInputFormatter(),
],
validator: (value) => InputValidators()
.emailValidator(value ?? ""),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: AppTextFormFieldWidget(
controller: controller.cpfCreate,
labelText: 'CPF',
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
CpfInputFormatter(),
],
validator: (value) =>
InputValidators().passwordValidator(value!),
),
),
],
),
),
),
],
),
),
),
),
SafeArea(
child: Scaffold(
backgroundColor: AppColors.background,
body: SingleChildScrollView(
child: Stack(
children: <Widget>[
Positioned(
top: 74,
left: 48,
child: Image.asset(
'assets/images/logo_budget.png',
height: 53.85,
width: 100,
),
),
Positioned(
top: 144,
left: 48,
child: SizedBox(
width: 255.0,
height: 86.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Bem-Vindo!',
style: TextStyles.h3HeadCreateAccount,
),
Text(
"Leia com atenção e aceite.",
style: TextStyles.h6HeadCreateAccount,
)
],
),
),
),
Container(
padding: EdgeInsets.only(top: 274, left: 27, right: 22),
child: Column(
children: [
Container(
height: 193.0,
width: 311.0,
child: Text(
"Lorem Ipsum neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit. Ipsum neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit. Nque porro est qui dolorem ipsum quia dolor sit amet, , adipisci velit. Quisquam est qui dolorem ipsum.",
style: TextStyles.blackRoboto16400,
)),
SizedBox(
height: 30.0,
),
Row(children: [
Container(
height: 48,
width: 48,
child: Radio<bool>(
value: policy ?? true,
groupValue: policy,
toggleable: true,
onChanged: (value) {
setState(() {
policy = value;
print(policy);
});
},
),
),
Container(
height: 48,
width: 272,
child: Text(
"Eu li e aceito os termos e condições e a Política de privacidade do budget.",
style: TextStyles.blackRoboto16400,
),
)
]),
],
),
),
],
),
),
),
),
SafeArea(
child: Scaffold(
backgroundColor: AppColors.background,
body: SingleChildScrollView(
child: Stack(
children: <Widget>[
Positioned(
top: 74,
left: 48,
child: Image.asset(
'assets/images/logo_budget.png',
height: 53.85,
width: 100,
),
),
Positioned(
top: 144,
left: 48,
child: SizedBox(
width: 255.0,
height: 118.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Bem-Vindo!',
style: TextStyles.h3HeadCreateAccount,
),
Text(
"Agora crie sua senha contendo:",
style: TextStyles.h6HeadCreateAccount,
)
],
),
),
),
Positioned(
top: 320,
child: Container(
margin: EdgeInsets.only(left: 60, right: 48),
height: 72,
width: 267,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"• pelo menos oito caracteres",
style: TextStyles.blackRoboto16400,
),
//TODO Verificar o campo com Bullet Point
Text(
"• letras maiúscula, letras minúsculas, números e símbolos",
style: TextStyles.blackRoboto16400,
),
],
),
),
),
Container(
padding: EdgeInsets.only(top: 419, left: 48, right: 48),
child: Form(
key: _formKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: AppTextFormFieldWidget(
controller: controller.passwordCreate,
hintText: 'Crie uma senha',
validator: (value) {
InputValidators().passwordValidator(value!);
}),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: AppTextFormFieldWidget(
controller:
controller.passwordCreateConfirmation,
hintText: 'Confirme sua senha',
validator: (value) {
if (value !=
controller.passwordCreate.text) {
return "As senhas não coincidem";
} else {
InputValidators()
.passwordValidator(value!);
}
}),
),
],
),
),
),
],
),
),
),
),
],
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: AnimatedBuilder(
animation: controller.pageViewController,
builder: (context, snapshot) {
return Padding(
padding: const EdgeInsets.only(left: 12),
child: Container(
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 116,
height: 48,
child: TextButton.icon(
icon: Icon(
Icons.arrow_back,
color: Color.fromRGBO(0, 0, 0, 0.26),
),
label: Text(
"VOLTAR",
style: TextStyle(
fontStyle: FontStyle.normal,
fontSize: 16,
fontFamily: "Roboto",
fontWeight: FontWeight.w500,
letterSpacing: 0.4,
textBaseline: TextBaseline.alphabetic,
color: Color.fromRGBO(0, 0, 0, 0.26),
),
),
onPressed: () {
if (currentPage == 0) {
Modular.to.popAndPushNamed('/initial');
} else {
controller.pageViewController.previousPage(
duration: Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
},
),
),
Text("${currentPage + 1}/4",
style: TextStyles
.createAccountTextStyleBottomNavigatorNumber),
Padding(
padding: const EdgeInsets.only(right: 12),
child: ElevatedButtonWidget(
mainAlign: MainAxisAlignment.spaceBetween,
fontSize: 14,
buttonText: "CONTINUAR ",
width: 116,
height: 32,
paddingValue: 4,
sufixicon: Icon(
Icons.arrow_forward,
size: 18,
),
onpressed: () {
if (currentPage == 3 &&
_formKey.currentState!.validate() &&
policy == true) {
final user = User(
cpf: controller.cpfCreate.value.text,
name: controller.nameCreate.value.text,
email: controller.emailCreate.value.text,
password: controller.passwordCreate.value.text,
telephone: controller.telefoneCreate.value.text,
policyAccepted: policy!,
);
print(user);
// Modular.to.popAndPushNamed(
// "create_account_module/onboard");
} else {
controller.pageViewController.nextPage(
duration: Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
}),
)
],
),
),
);
},
),
),
);
}
}
解决方案
_formKey 在 Widget 树中应该是唯一的。 https://api.flutter.dev/flutter/widgets/Widget/key.html
声明更多 GlobalKey() 并分配给每个 Form()
推荐阅读
- java - 为 orientDB 使用 vertex.setProperties() 函数时出错
- android - 无法在 Android Studio 上接受 sdk 许可证
- python - UnicodeEncodeError:“ascii”编解码器无法在打印函数中编码字符
- jquery - Fancybox 不能很好地与里面的表格一起工作
- python - 如何从图像中分离出手写数字候选者?
- linux - 从 datetime.now 经过 15 分钟的时间
- c++ - C ++通过另一个链接一个库
- php - 无法使用 phpmailer 在邮件中发送令牌和电子邮件值以忘记密码
- java - ObjectMapper 无法处理带有遗留枚举(类)的映射对象
- javascript - 在javascript中打印集合容器的特定元素