我正在尝试使用 flutter reactive_forms对两种表单进行条件渲染。但是,当我输入一个表单,然后单击将另一个表单呈现在完全相同的位置的按钮时,相同的值也会保留在另一个表单中。唯一改变表单控件标签的东西。这些表格只是彼此重复。我已经尝试了很多方法来使值不重复,但无济于事。我很长一段时间以来最糟糕的编程经历之一。
这是我FormGroup
最初用于两种表单的我的,因为我确实希望大多数字段都重复,但并非所有字段,例如“groceryStore”和“restaurant”,都不会在两种表单之间共享。我什FormGroup
至尝试为每个具有所有完全唯一的字段名称使用单独FormGroup
的... 就像它与其他条件表单字段在页面上的相同位置一样,因此它将保持其值。当我离开页面并返回页面时,我首先查看的表单具有正确的不同值。我的代码:
FormGroup form = FormGroup({
VeganItemFieldNames.name:
FormControl<String>(validators: [Validators.required]),
VeganItemFieldNames.brand:
FormControl<String>(validators: [Validators.required]),
VeganItemFieldNames.description:
FormControl<String>(validators: [Validators.required]),
VeganItemFieldNames.price:
FormControl<double>(validators: [Validators.required]),
VeganItemFieldNames.groceryStore:
FormControl<String>(validators: [Validators.required]),
VeganItemFieldNames.restaurant:
FormControl<String>(validators: [Validators.required]),
// VeganItemFieldNames.groceryItemCategories: FormControl<String>(),
// VeganItemFieldNames.menuItemCategories: FormControl<String>(),
VeganItemFieldNames.image:
FormControl<String>(validators: [Validators.required]),
});
我的观点:
child: ReactiveForm(
formGroup: viewModelState.form,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 7,
child: KeyboardAvoider(
autoScroll: true,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
if (viewModel.addVeganItemStrategy !=
null)
...viewModel.buildFields(context)
]))),
Container(
padding: const EdgeInsets.fromLTRB(
PAD_0, PAD_1, PAD_0, PAD_3),
child: Center(
child: VpSubmitButton(
text: 'Submit', onPressed: () {})))
]))
视图模型:
List<Widget> buildFields(BuildContext context1) {
return addVeganItemStrategy.buildFields(
context: context, form: viewModelState.form);
}
一种策略 buildFields()
class AddGroceryItemStrategy implements AddVeganItemStrategy {
List<Widget> buildFields({BuildContext context, FormGroup form}) {
return [
nameTextField(context: context, form: form),
brandTextField(context: context),
groceryStoreTextField(context: context),
descriptionTextField(context: context),
priceTextField(context: context),
// groceryItemCategoriesTextField(context: context, form: form),
imageTextField(context: context),
];
}
Widget nameTextField(
{BuildContext context, FormGroup form, String nextField}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_4, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Name',
maxLength: 40,
formControlName: GroceryItemFieldNames.name,
hintText: 'Name...',
form: form,
textInputAction: TextInputAction.next,
nextField: nextField,
validationMessages: (control) => {
'required': 'Please enter the Product Name',
}));
}
Widget brandTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Brand',
maxLength: 30,
formControlName: GroceryItemFieldNames.brand,
hintText: 'Brand...',
validationMessages: (control) =>
{'required': 'Please enter the Product Brand'},
));
}
Widget groceryStoreTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Grocery Store',
formControlName: GroceryItemFieldNames.groceryStore,
hintText: 'Grocery Store...',
validationMessages: (control) =>
{'required': 'Please enter the Grocery Store'},
));
}
Widget descriptionTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
maxLength: 150,
labelText: 'Description',
formControlName: GroceryItemFieldNames.description,
hintText: 'Description...',
validationMessages: (control) =>
{'required': 'Please enter the Product Description'},
));
}
Widget priceTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
textInputType: TextInputType.number,
context: context,
labelText: 'Price',
formControlName: GroceryItemFieldNames.price,
hintText: 'Price...',
validationMessages: (control) =>
{'required': 'Please enter the Product Price'},
));
}
Widget groceryItemCategoriesTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Categories',
formControlName: GroceryItemFieldNames.groceryItemCategories,
hintText: 'Categories...',
validationMessages: (control) =>
{'required': 'Please enter the Product Categories'},
));
}
Widget imageTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Image',
formControlName: GroceryItemFieldNames.image,
hintText: 'Image...',
validationMessages: (control) =>
{'required': 'Please enter the Product Image'},
));
}
}
另一个策略 buildFields:
class AddMenuItemStrategy implements AddVeganItemStrategy {
List<Widget> buildFields({BuildContext context, FormGroup form}) {
return [
nameTextField(context: context, form: form),
restaurantTextField(context: context),
descriptionTextField(context: context),
priceTextField(context: context),
// menuItemCategoriesTextField(context: context, form: form),
imageTextField(context: context),
];
}
Widget nameTextField(
{BuildContext context, FormGroup form, String nextField}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_4, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Name',
maxLength: 40,
formControlName: MenuItemFieldNames.name,
hintText: 'Name...',
form: form,
textInputAction: TextInputAction.next,
nextField: nextField,
validationMessages: (control) => {
'required': 'Please enter the Product Name',
}));
}
Widget restaurantTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Restaurant',
formControlName: MenuItemFieldNames.restaurant,
hintText: 'Restaurant...',
validationMessages: (control) =>
{'required': 'Please enter the Restaurant'},
));
}
Widget descriptionTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
maxLength: 150,
labelText: 'Description',
formControlName: MenuItemFieldNames.description,
hintText: 'Description...',
validationMessages: (control) =>
{'required': 'Please enter the Menu Item Description'},
));
}
Widget priceTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
textInputType: TextInputType.number,
context: context,
labelText: 'Price',
formControlName: MenuItemFieldNames.price,
hintText: 'Price...',
validationMessages: (control) =>
{'required': 'Please enter the Menu Item Price'},
));
}
Widget menuItemCategoriesTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Categories',
formControlName: MenuItemFieldNames.menuItemCategories,
hintText: 'Categories...',
validationMessages: (control) =>
{'required': 'Please enter the Menu Item Categories'},
));
}
Widget imageTextField({BuildContext context}) {
return Container(
padding:
const EdgeInsets.fromLTRB(PAD_3_HALF, PAD_0, PAD_3_HALF, PAD_4),
child: VpTextField(
context: context,
labelText: 'Image',
formControlName: MenuItemFieldNames.image,
hintText: 'Image...',
validationMessages: (control) =>
{'required': 'Please enter the Menu Item Image'},
));
}