Improve form validation

This commit is contained in:
Hillel Coren 2022-10-02 16:29:34 +03:00
parent 191859e18a
commit fbc19db942
13 changed files with 255 additions and 215 deletions

View File

@ -117,7 +117,7 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
} }
} }
void _onSavePressed() { void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate(); final bool isValid = _formKey.currentState.validate();
if (!isValid) { if (!isValid) {
@ -191,7 +191,7 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
validator: (String val) => !viewModel.client.hasNameSet validator: (String val) => !viewModel.client.hasNameSet
? AppLocalization.of(context).pleaseEnterAClientOrContactName ? AppLocalization.of(context).pleaseEnterAClientOrContactName
: null, : null,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
label: localization.name, label: localization.name,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
decoration: !kIsWeb && (Platform.isIOS || Platform.isAndroid) decoration: !kIsWeb && (Platform.isIOS || Platform.isAndroid)
@ -219,7 +219,7 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
DecoratedFormField( DecoratedFormField(
label: localization.number, label: localization.number,
controller: _numberController, controller: _numberController,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
if (memoizedGroupList(state.groupState.map).isNotEmpty) if (memoizedGroupList(state.groupState.map).isNotEmpty)
@ -238,50 +238,50 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
DecoratedFormField( DecoratedFormField(
label: localization.idNumber, label: localization.idNumber,
controller: _idNumberController, controller: _idNumberController,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DecoratedFormField( DecoratedFormField(
label: localization.vatNumber, label: localization.vatNumber,
controller: _vatNumberController, controller: _vatNumberController,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DecoratedFormField( DecoratedFormField(
label: localization.website, label: localization.website,
controller: _websiteController, controller: _websiteController,
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
), ),
DecoratedFormField( DecoratedFormField(
label: localization.phone, label: localization.phone,
controller: _phoneController, controller: _phoneController,
keyboardType: TextInputType.phone, keyboardType: TextInputType.phone,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom1Controller, controller: _custom1Controller,
field: CustomFieldType.client1, field: CustomFieldType.client1,
value: client.customValue1, value: client.customValue1,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom2Controller, controller: _custom2Controller,
field: CustomFieldType.client2, field: CustomFieldType.client2,
value: client.customValue2, value: client.customValue2,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom3Controller, controller: _custom3Controller,
field: CustomFieldType.client3, field: CustomFieldType.client3,
value: client.customValue3, value: client.customValue3,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom4Controller, controller: _custom4Controller,
field: CustomFieldType.client4, field: CustomFieldType.client4,
value: client.customValue4, value: client.customValue4,
onSavePressed: (_) => _onSavePressed(), onSavePressed: _onSavePressed,
), ),
], ],
), ),

View File

@ -132,6 +132,16 @@ class _ProductEditState extends State<ProductEdit> {
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
@ -145,15 +155,7 @@ class _ProductEditState extends State<ProductEdit> {
? localization.newProduct ? localization.newProduct
: localization.editProduct, : localization.editProduct,
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
body: AppForm( body: AppForm(
formKey: _formKey, formKey: _formKey,
focusNode: _focusNode, focusNode: _focusNode,
@ -170,7 +172,7 @@ class _ProductEditState extends State<ProductEdit> {
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterAProductKey ? localization.pleaseEnterAProductKey
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DecoratedFormField( DecoratedFormField(
@ -184,7 +186,7 @@ class _ProductEditState extends State<ProductEdit> {
controller: _priceController, controller: _priceController,
keyboardType: TextInputType.numberWithOptions( keyboardType: TextInputType.numberWithOptions(
decimal: true, signed: true), decimal: true, signed: true),
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
if (company.enableProductQuantity) if (company.enableProductQuantity)
DecoratedFormField( DecoratedFormField(
@ -192,7 +194,7 @@ class _ProductEditState extends State<ProductEdit> {
controller: _quantityController, controller: _quantityController,
keyboardType: TextInputType.numberWithOptions( keyboardType: TextInputType.numberWithOptions(
decimal: true, signed: true), decimal: true, signed: true),
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
if (company.enableProductCost) if (company.enableProductCost)
DecoratedFormField( DecoratedFormField(
@ -200,7 +202,7 @@ class _ProductEditState extends State<ProductEdit> {
controller: _costController, controller: _costController,
keyboardType: TextInputType.numberWithOptions( keyboardType: TextInputType.numberWithOptions(
decimal: true, signed: true), decimal: true, signed: true),
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
if (company.enableFirstItemTaxRate || if (company.enableFirstItemTaxRate ||
product.taxName1.isNotEmpty) product.taxName1.isNotEmpty)
@ -239,32 +241,32 @@ class _ProductEditState extends State<ProductEdit> {
controller: _custom1Controller, controller: _custom1Controller,
field: CustomFieldType.product1, field: CustomFieldType.product1,
value: product.customValue1, value: product.customValue1,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom2Controller, controller: _custom2Controller,
field: CustomFieldType.product2, field: CustomFieldType.product2,
value: product.customValue2, value: product.customValue2,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom3Controller, controller: _custom3Controller,
field: CustomFieldType.product3, field: CustomFieldType.product3,
value: product.customValue3, value: product.customValue3,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom4Controller, controller: _custom4Controller,
field: CustomFieldType.product4, field: CustomFieldType.product4,
value: product.customValue4, value: product.customValue4,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
if (company.trackInventory) ...[ if (company.trackInventory) ...[
DecoratedFormField( DecoratedFormField(
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
controller: _stockQuantityController, controller: _stockQuantityController,
label: localization.stockQuantity, label: localization.stockQuantity,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
if (company.stockNotification) ...[ if (company.stockNotification) ...[
SizedBox(height: 16), SizedBox(height: 16),
@ -284,7 +286,7 @@ class _ProductEditState extends State<ProductEdit> {
company.stockNotificationThreshold != 0) company.stockNotificationThreshold != 0)
? '${localization.defaultWord} ${company.stockNotificationThreshold}' ? '${localization.defaultWord} ${company.stockNotificationThreshold}'
: ''), : ''),
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
], ],
], ],

View File

@ -116,6 +116,16 @@ class _ProjectEditState extends State<ProjectEdit> {
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -127,15 +137,7 @@ class _ProjectEditState extends State<ProjectEdit> {
entity: project, entity: project,
title: project.isNew ? localization.newProject : localization.editProject, title: project.isNew ? localization.newProject : localization.editProject,
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
body: Form( body: Form(
key: _formKey, key: _formKey,
child: Builder(builder: (BuildContext context) { child: Builder(builder: (BuildContext context) {
@ -153,7 +155,7 @@ class _ProjectEditState extends State<ProjectEdit> {
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
autofocus: true, autofocus: true,
label: localization.projectName, label: localization.projectName,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
project.isNew project.isNew
? EntityDropdown( ? EntityDropdown(
@ -180,7 +182,7 @@ class _ProjectEditState extends State<ProjectEdit> {
controller: _numberController, controller: _numberController,
label: localization.projectNumber, label: localization.projectNumber,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
UserPicker( UserPicker(
userId: project.assignedUserId, userId: project.assignedUserId,
@ -200,38 +202,38 @@ class _ProjectEditState extends State<ProjectEdit> {
decimal: true, signed: true), decimal: true, signed: true),
controller: _hoursController, controller: _hoursController,
label: localization.budgetedHours, label: localization.budgetedHours,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
DecoratedFormField( DecoratedFormField(
keyboardType: TextInputType.numberWithOptions( keyboardType: TextInputType.numberWithOptions(
decimal: true, signed: true), decimal: true, signed: true),
controller: _taskRateController, controller: _taskRateController,
label: localization.taskRate, label: localization.taskRate,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom1Controller, controller: _custom1Controller,
field: CustomFieldType.project1, field: CustomFieldType.project1,
value: project.customValue1, value: project.customValue1,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom2Controller, controller: _custom2Controller,
field: CustomFieldType.project2, field: CustomFieldType.project2,
value: project.customValue2, value: project.customValue2,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom3Controller, controller: _custom3Controller,
field: CustomFieldType.project3, field: CustomFieldType.project3,
value: project.customValue3, value: project.customValue3,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom4Controller, controller: _custom4Controller,
field: CustomFieldType.project4, field: CustomFieldType.project4,
value: project.customValue4, value: project.customValue4,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
DecoratedFormField( DecoratedFormField(
maxLines: 4, maxLines: 4,

View File

@ -341,7 +341,7 @@ class _ClientPortalState extends State<ClientPortal>
state.isHosted state.isHosted
? localization.pleaseEnterAValue ? localization.pleaseEnterAValue
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
SizedBox(height: 16), SizedBox(height: 16),
if (state.isEnterprisePlan) if (state.isEnterprisePlan)

View File

@ -268,9 +268,11 @@ class _CompanyDetailsState extends State<CompanyDetails>
DecoratedFormField( DecoratedFormField(
label: localization.name, label: localization.name,
controller: _nameController, controller: _nameController,
/*
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterAName ? localization.pleaseEnterAName
: null, : null,
*/
onSavePressed: viewModel.onSavePressed, onSavePressed: viewModel.onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),

View File

@ -40,7 +40,6 @@ class _EmailSettingsState extends State<EmailSettings> {
GlobalKey<FormState>(debugLabel: '_emailSettings'); GlobalKey<FormState>(debugLabel: '_emailSettings');
FocusScopeNode _focusNode; FocusScopeNode _focusNode;
bool autoValidate = false;
final _fromNameController = TextEditingController(); final _fromNameController = TextEditingController();
final _replyToEmailController = TextEditingController(); final _replyToEmailController = TextEditingController();

View File

@ -138,6 +138,16 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -186,15 +196,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
? localization.newSubscription ? localization.newSubscription
: localization.editSubscription, : localization.editSubscription,
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
appBarBottom: TabBar( appBarBottom: TabBar(
key: ValueKey(state.settingsUIState.updatedAt), key: ValueKey(state.settingsUIState.updatedAt),
controller: _controller, controller: _controller,
@ -223,7 +225,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
DecoratedFormField( DecoratedFormField(
controller: _nameController, controller: _nameController,
label: localization.name, label: localization.name,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DynamicSelector( DynamicSelector(
@ -371,7 +373,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
DecoratedFormField( DecoratedFormField(
label: localization.promoCode, label: localization.promoCode,
controller: _promoCodeController, controller: _promoCodeController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DiscountField( DiscountField(
@ -391,7 +393,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
label: localization.returnUrl, label: localization.returnUrl,
controller: _returnUrlController, controller: _returnUrlController,
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
BoolDropdownButton( BoolDropdownButton(
label: localization.allowQueryOverrides, label: localization.allowQueryOverrides,
@ -447,7 +449,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
inputFormatters: [ inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')), FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
], ],
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
], ],
) )
@ -461,7 +463,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
label: localization.webhookUrl, label: localization.webhookUrl,
controller: _postPurchaseUrlController, controller: _postPurchaseUrlController,
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
AppDropdownButton<String>( AppDropdownButton<String>(
showBlank: true, showBlank: true,
@ -487,7 +489,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
child: DecoratedFormField( child: DecoratedFormField(
label: localization.headerKey, label: localization.headerKey,
controller: _postPurchaseHeaderKeyController, controller: _postPurchaseHeaderKeyController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
onChanged: (value) => setState(() {}), onChanged: (value) => setState(() {}),
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
@ -499,7 +501,7 @@ class _SubscriptionEditState extends State<SubscriptionEdit>
child: DecoratedFormField( child: DecoratedFormField(
label: localization.headerValue, label: localization.headerValue,
controller: _postPurchaseHeaderValueController, controller: _postPurchaseHeaderValueController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
onChanged: (value) => setState(() {}), onChanged: (value) => setState(() {}),
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),

View File

@ -68,6 +68,16 @@ class _TaskStatusEditState extends State<TaskStatusEdit> {
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -80,15 +90,7 @@ class _TaskStatusEditState extends State<TaskStatusEdit> {
? localization.newTaskStatus ? localization.newTaskStatus
: localization.editTaskStatus, : localization.editTaskStatus,
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
body: Form( body: Form(
key: _formKey, key: _formKey,
child: Builder(builder: (BuildContext context) { child: Builder(builder: (BuildContext context) {
@ -104,7 +106,7 @@ class _TaskStatusEditState extends State<TaskStatusEdit> {
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterAName ? localization.pleaseEnterAName
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
FormColorPicker( FormColorPicker(
initialValue: taskStatus.color, initialValue: taskStatus.color,

View File

@ -75,6 +75,16 @@ class _TaxRateEditState extends State<TaxRateEdit> {
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -85,7 +95,7 @@ class _TaxRateEditState extends State<TaxRateEdit> {
title: viewModel.taxRate.isNew title: viewModel.taxRate.isNew
? localization.newTaxRate ? localization.newTaxRate
: localization.editTaxRate, : localization.editTaxRate,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
onCancelPressed: viewModel.onCancelPressed, onCancelPressed: viewModel.onCancelPressed,
body: AppForm( body: AppForm(
focusNode: _focusNode, focusNode: _focusNode,
@ -100,14 +110,14 @@ class _TaxRateEditState extends State<TaxRateEdit> {
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterAName ? localization.pleaseEnterAName
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DecoratedFormField( DecoratedFormField(
label: localization.rate, label: localization.rate,
controller: _rateController, controller: _rateController,
isPercent: true, isPercent: true,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.numberWithOptions(decimal: true), keyboardType: TextInputType.numberWithOptions(decimal: true),
), ),
], ],

View File

@ -67,6 +67,16 @@ class _TokenEditState extends State<TokenEdit> {
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -77,15 +87,7 @@ class _TokenEditState extends State<TokenEdit> {
entity: token, entity: token,
title: token.isNew ? localization.newToken : localization.editToken, title: token.isNew ? localization.newToken : localization.editToken,
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
body: Form( body: Form(
key: _formKey, key: _formKey,
child: Builder(builder: (BuildContext context) { child: Builder(builder: (BuildContext context) {
@ -101,7 +103,7 @@ class _TokenEditState extends State<TokenEdit> {
value.isEmpty || value.trim().isEmpty value.isEmpty || value.trim().isEmpty
? localization.pleaseEnterAName ? localization.pleaseEnterAName
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
], ],

View File

@ -139,6 +139,16 @@ class _UserEditState extends State<UserEdit>
user.rebuild((b) => b..userCompany.permissions = permissionsString)); user.rebuild((b) => b..userCompany.permissions = permissionsString));
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -167,15 +177,7 @@ class _UserEditState extends State<UserEdit>
], ],
), ),
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
body: AppTabForm( body: AppTabForm(
focusNode: _focusNode, focusNode: _focusNode,
formKey: _formKey, formKey: _formKey,
@ -192,7 +194,7 @@ class _UserEditState extends State<UserEdit>
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterAFirstName ? localization.pleaseEnterAFirstName
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.name, keyboardType: TextInputType.name,
), ),
DecoratedFormField( DecoratedFormField(
@ -201,7 +203,7 @@ class _UserEditState extends State<UserEdit>
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterALastName ? localization.pleaseEnterALastName
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.name, keyboardType: TextInputType.name,
), ),
DecoratedFormField( DecoratedFormField(
@ -210,45 +212,45 @@ class _UserEditState extends State<UserEdit>
validator: (val) => val.isEmpty || val.trim().isEmpty validator: (val) => val.isEmpty || val.trim().isEmpty
? localization.pleaseEnterYourEmail ? localization.pleaseEnterYourEmail
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
), ),
DecoratedFormField( DecoratedFormField(
label: localization.phone, label: localization.phone,
controller: _phoneController, controller: _phoneController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.phone, keyboardType: TextInputType.phone,
), ),
/* /*
PasswordFormField( PasswordFormField(
controller: _passwordController, controller: _passwordController,
autoValidate: autoValidate, autoValidate: autoValidate,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
*/ */
CustomField( CustomField(
controller: _custom1Controller, controller: _custom1Controller,
field: CustomFieldType.user1, field: CustomFieldType.user1,
value: user.customValue1, value: user.customValue1,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom2Controller, controller: _custom2Controller,
field: CustomFieldType.user2, field: CustomFieldType.user2,
value: user.customValue2, value: user.customValue2,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom3Controller, controller: _custom3Controller,
field: CustomFieldType.user3, field: CustomFieldType.user3,
value: user.customValue3, value: user.customValue3,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom4Controller, controller: _custom4Controller,
field: CustomFieldType.user4, field: CustomFieldType.user4,
value: user.customValue4, value: user.customValue4,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
], ],
), ),

View File

@ -44,6 +44,8 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
final _custom3Controller = TextEditingController(); final _custom3Controller = TextEditingController();
final _custom4Controller = TextEditingController(); final _custom4Controller = TextEditingController();
static final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: '_vendorEditDetails');
final _debouncer = Debouncer(); final _debouncer = Debouncer();
List<TextEditingController> _controllers; List<TextEditingController> _controllers;
@ -151,6 +153,16 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
..updatedAt = DateTime.now().millisecondsSinceEpoch)); ..updatedAt = DateTime.now().millisecondsSinceEpoch));
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
@ -159,7 +171,9 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
final state = viewModel.state; final state = viewModel.state;
final isFullscreen = state.prefState.isEditorFullScreen(EntityType.vendor); final isFullscreen = state.prefState.isEditorFullScreen(EntityType.vendor);
return FormCard( return Form(
key: _formKey,
child: FormCard(
isLast: true, isLast: true,
padding: isFullscreen padding: isFullscreen
? const EdgeInsets.only( ? const EdgeInsets.only(
@ -175,7 +189,7 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
validator: (String val) => val == null || val.isEmpty validator: (String val) => val == null || val.isEmpty
? AppLocalization.of(context).pleaseEnterAName ? AppLocalization.of(context).pleaseEnterAName
: null, : null,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
label: localization.name, label: localization.name,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
decoration: !kIsWeb && (Platform.isIOS || Platform.isAndroid) decoration: !kIsWeb && (Platform.isIOS || Platform.isAndroid)
@ -203,7 +217,7 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
DecoratedFormField( DecoratedFormField(
label: localization.number, label: localization.number,
controller: _numberController, controller: _numberController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
UserPicker( UserPicker(
@ -214,52 +228,53 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
DecoratedFormField( DecoratedFormField(
controller: _idNumberController, controller: _idNumberController,
label: localization.idNumber, label: localization.idNumber,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DecoratedFormField( DecoratedFormField(
controller: _vatNumberController, controller: _vatNumberController,
label: localization.vatNumber, label: localization.vatNumber,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
DecoratedFormField( DecoratedFormField(
controller: _websiteController, controller: _websiteController,
label: localization.website, label: localization.website,
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
DecoratedFormField( DecoratedFormField(
controller: _phoneController, controller: _phoneController,
label: localization.phone, label: localization.phone,
keyboardType: TextInputType.phone, keyboardType: TextInputType.phone,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom1Controller, controller: _custom1Controller,
field: CustomFieldType.vendor1, field: CustomFieldType.vendor1,
value: vendor.customValue1, value: vendor.customValue1,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom2Controller, controller: _custom2Controller,
field: CustomFieldType.vendor2, field: CustomFieldType.vendor2,
value: vendor.customValue2, value: vendor.customValue2,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom3Controller, controller: _custom3Controller,
field: CustomFieldType.vendor3, field: CustomFieldType.vendor3,
value: vendor.customValue3, value: vendor.customValue3,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
CustomField( CustomField(
controller: _custom4Controller, controller: _custom4Controller,
field: CustomFieldType.vendor4, field: CustomFieldType.vendor4,
value: vendor.customValue4, value: vendor.customValue4,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
), ),
], ],
),
); );
} }
} }

View File

@ -75,6 +75,16 @@ class _WebhookEditState extends State<WebhookEdit> {
} }
} }
void _onSavePressed(BuildContext context) {
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
widget.viewModel.onSavePressed(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
@ -88,15 +98,7 @@ class _WebhookEditState extends State<WebhookEdit> {
entity: webhook, entity: webhook,
title: webhook.isNew ? localization.newWebhook : localization.editWebhook, title: webhook.isNew ? localization.newWebhook : localization.editWebhook,
onCancelPressed: (context) => viewModel.onCancelPressed(context), onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) { onSavePressed: _onSavePressed,
final bool isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
},
body: Form( body: Form(
key: _formKey, key: _formKey,
child: Builder(builder: (BuildContext context) { child: Builder(builder: (BuildContext context) {
@ -150,7 +152,7 @@ class _WebhookEditState extends State<WebhookEdit> {
child: DecoratedFormField( child: DecoratedFormField(
label: localization.headerKey, label: localization.headerKey,
controller: _headerKeyController, controller: _headerKeyController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
onChanged: (value) => setState(() {}), onChanged: (value) => setState(() {}),
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
@ -162,7 +164,7 @@ class _WebhookEditState extends State<WebhookEdit> {
child: DecoratedFormField( child: DecoratedFormField(
label: localization.headerValue, label: localization.headerValue,
controller: _headerValueController, controller: _headerValueController,
onSavePressed: viewModel.onSavePressed, onSavePressed: _onSavePressed,
onChanged: (value) => setState(() {}), onChanged: (value) => setState(() {}),
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),