From 20011bb3324956b2a85c9d6142d85ab1e268088d Mon Sep 17 00:00:00 2001 From: Vasiliy Ditsyak Date: Sat, 1 Jun 2024 22:46:22 +0200 Subject: [PATCH] first iteration of toOutput --- .../reactive_forms_annotations/CHANGELOG.md | 4 + .../lib/src/form_model.dart | 6 +- .../reactive_forms_annotations/pubspec.yaml | 2 +- .../reactive_forms_generator/CHANGELOG.md | 4 + .../example/.gitignore | 1 + .../lib/docs/animated_url_list/url.gform.dart | 4 +- .../docs/annotateless/annotateless.gform.dart | 2 +- .../array_nullable/array_nullable.gform.dart | 2 +- .../delivery_list/delivery_list.gform.dart | 11 +- .../lib/docs/freezed/freezed_class.gform.dart | 2 +- .../example/lib/docs/freezed2/test.gform.dart | 2 +- .../lib/docs/generic/generic.gform.dart | 2 +- .../generic_status_list.gform.dart | 3 +- .../example/lib/docs/group/group.gform.dart | 8 +- .../example/lib/docs/login/login.gform.dart | 2 +- .../lib/docs/login/login_output.gform.dart | 48 +++-- .../lib/docs/login/login_output_form.dart | 177 ++++++++++++++++++ .../example/lib/docs/login/mocks.dart | 3 + .../login_extended/login_extended.gform.dart | 2 +- .../login_extended_nullable.gform.dart | 3 +- .../docs/mailing_list/mailing_list.gform.dart | 2 +- .../model_extends/model_extends.gform.dart | 2 +- .../model_extends/model_extends_form.dart | 3 +- .../model_implements.gform.dart | 3 +- .../model_implements_form.dart | 3 +- .../example/lib/docs/nested/nested.gform.dart | 6 +- .../lib/docs/profile/profile.gform.dart | 10 +- .../renamed_basic/renamed_basic.gform.dart | 2 +- .../renamed_basic/renamed_basic_form.dart | 3 +- .../docs/user_profile/user_profile.gform.dart | 4 +- .../example/lib/drawer.dart | 6 + .../example/lib/main.dart | 4 + .../lib/src/extensions.dart | 5 +- .../form_elements/form_element_generator.dart | 8 +- .../lib/src/form_generator.dart | 80 ++++---- .../lib/src/library_builder.dart | 1 - .../src/reactive_form_generator_method.dart | 21 ++- .../reactive_form_update_value_method.dart | 4 +- .../reactive_forms_clear_method.dart | 2 +- .../reactive_forms_insert_method.dart | 2 +- .../reactive_forms_patch_value_method.dart | 4 +- .../contains_method.dart | 2 +- .../control_method.dart | 13 +- .../control_path_method.dart | 2 +- .../control_private_method.dart | 2 +- .../control_set_enabled_method.dart | 6 +- .../errors_method.dart | 4 +- .../extended_control_method.dart | 2 +- .../field_value_method.dart | 17 +- .../focus_method.dart | 2 +- .../remove_method.dart | 2 +- .../reset_method.dart | 4 +- .../lib/src/types.dart | 10 + .../reactive_forms_generator/pubspec.yaml | 2 +- 54 files changed, 393 insertions(+), 138 deletions(-) create mode 100644 packages/reactive_forms_generator/example/lib/docs/login/login_output_form.dart diff --git a/packages/reactive_forms_annotations/CHANGELOG.md b/packages/reactive_forms_annotations/CHANGELOG.md index bfe0212a..2d99ad6b 100644 --- a/packages/reactive_forms_annotations/CHANGELOG.md +++ b/packages/reactive_forms_annotations/CHANGELOG.md @@ -1,3 +1,7 @@ +## [6.0.0-beta.0] + +* output + ## [5.0.0] * rf17 diff --git a/packages/reactive_forms_annotations/lib/src/form_model.dart b/packages/reactive_forms_annotations/lib/src/form_model.dart index 34d6b331..17934271 100644 --- a/packages/reactive_forms_annotations/lib/src/form_model.dart +++ b/packages/reactive_forms_annotations/lib/src/form_model.dart @@ -1,16 +1,16 @@ import 'package:reactive_forms/reactive_forms.dart'; -abstract class FormModel { +abstract class FormModel { FormModel({ required this.form, }); final FormGroup form; - TModel get model; + TModelOutput get model; void submit({ - required void Function(TModel model) onValid, + required void Function(TModelOutput model) onValid, void Function()? onNotValid, }); diff --git a/packages/reactive_forms_annotations/pubspec.yaml b/packages/reactive_forms_annotations/pubspec.yaml index 0b5e0519..a80fc612 100644 --- a/packages/reactive_forms_annotations/pubspec.yaml +++ b/packages/reactive_forms_annotations/pubspec.yaml @@ -16,7 +16,7 @@ repository: https://github.com/artflutter/reactive_forms_generator # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 5.0.0 +version: 6.0.0-beta.0 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/packages/reactive_forms_generator/CHANGELOG.md b/packages/reactive_forms_generator/CHANGELOG.md index ebc8584d..a352ab98 100644 --- a/packages/reactive_forms_generator/CHANGELOG.md +++ b/packages/reactive_forms_generator/CHANGELOG.md @@ -1,3 +1,7 @@ +## [6.0.0-beta.0] + +* output + ## [5.0.1] * error type fix diff --git a/packages/reactive_forms_generator/example/.gitignore b/packages/reactive_forms_generator/example/.gitignore index a1345d01..29a64f85 100644 --- a/packages/reactive_forms_generator/example/.gitignore +++ b/packages/reactive_forms_generator/example/.gitignore @@ -14,6 +14,7 @@ *.ipr *.iws .idea/ +linux # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line diff --git a/packages/reactive_forms_generator/example/lib/docs/animated_url_list/url.gform.dart b/packages/reactive_forms_generator/example/lib/docs/animated_url_list/url.gform.dart index 829b0430..36f3f020 100644 --- a/packages/reactive_forms_generator/example/lib/docs/animated_url_list/url.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/animated_url_list/url.gform.dart @@ -179,7 +179,7 @@ class _UrlFormBuilderState extends State { } } -class UrlForm implements FormModel { +class UrlForm implements FormModel { UrlForm( this.form, this.path, @@ -472,7 +472,7 @@ class UrlForm implements FormModel { disabled: false); } -class UrlEntityForm implements FormModel { +class UrlEntityForm implements FormModel { UrlEntityForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless.gform.dart b/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless.gform.dart index 3172c433..a0430641 100644 --- a/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless.gform.dart @@ -185,7 +185,7 @@ class _AnnotatelessFormBuilderState extends State { } } -class AnnotatelessForm implements FormModel { +class AnnotatelessForm implements FormModel { AnnotatelessForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable.gform.dart b/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable.gform.dart index 76b08304..4f78a522 100644 --- a/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable.gform.dart @@ -185,7 +185,7 @@ class _ArrayNullableFormBuilderState extends State { } } -class ArrayNullableForm implements FormModel { +class ArrayNullableForm implements FormModel { ArrayNullableForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list.gform.dart b/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list.gform.dart index 36dd5b14..41ecc72e 100644 --- a/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list.gform.dart @@ -185,7 +185,7 @@ class _DeliveryListFormBuilderState extends State { } } -class DeliveryListForm implements FormModel { +class DeliveryListForm implements FormModel { DeliveryListForm( this.form, this.path, @@ -702,7 +702,7 @@ class DeliveryListForm implements FormModel { disabled: false); } -class DeliveryPointForm implements FormModel { +class DeliveryPointForm implements FormModel { DeliveryPointForm( this.form, this.path, @@ -982,7 +982,7 @@ class DeliveryPointForm implements FormModel { disabled: false); } -class AddressForm implements FormModel
{ +class AddressForm implements FormModel { AddressForm( this.form, this.path, @@ -1290,7 +1290,7 @@ class AddressForm implements FormModel
{ disabled: false); } -class ClientForm implements FormModel { +class ClientForm implements FormModel { ClientForm( this.form, this.path, @@ -1984,7 +1984,8 @@ class _StandaloneDeliveryPointFormBuilderState } } -class StandaloneDeliveryPointForm implements FormModel { +class StandaloneDeliveryPointForm + implements FormModel { StandaloneDeliveryPointForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class.gform.dart b/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class.gform.dart index 06a44156..561e2ef4 100644 --- a/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class.gform.dart @@ -185,7 +185,7 @@ class _FreezedClassFormBuilderState extends State { } } -class FreezedClassForm implements FormModel { +class FreezedClassForm implements FormModel { FreezedClassForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/freezed2/test.gform.dart b/packages/reactive_forms_generator/example/lib/docs/freezed2/test.gform.dart index dc582031..241d7417 100644 --- a/packages/reactive_forms_generator/example/lib/docs/freezed2/test.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/freezed2/test.gform.dart @@ -179,7 +179,7 @@ class _TestFormBuilderState extends State { } } -class TestForm implements FormModel { +class TestForm implements FormModel { TestForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/generic/generic.gform.dart b/packages/reactive_forms_generator/example/lib/docs/generic/generic.gform.dart index 174365e9..218d7aa3 100644 --- a/packages/reactive_forms_generator/example/lib/docs/generic/generic.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/generic/generic.gform.dart @@ -179,7 +179,7 @@ class _TagsFormBuilderState extends State> { } } -class TagsForm implements FormModel> { +class TagsForm implements FormModel, Tags> { TagsForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list.gform.dart b/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list.gform.dart index f1073408..849d6a1f 100644 --- a/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list.gform.dart @@ -187,7 +187,8 @@ class _StatusListFormBuilderState } } -class StatusListForm implements FormModel> { +class StatusListForm + implements FormModel, StatusList> { StatusListForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/group/group.gform.dart b/packages/reactive_forms_generator/example/lib/docs/group/group.gform.dart index c4d92588..6f07cffb 100644 --- a/packages/reactive_forms_generator/example/lib/docs/group/group.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/group/group.gform.dart @@ -179,7 +179,7 @@ class _GroupFormBuilderState extends State { } } -class GroupForm implements FormModel { +class GroupForm implements FormModel { GroupForm( this.form, this.path, @@ -693,7 +693,7 @@ class GroupForm implements FormModel { disabled: false); } -class PersonalForm implements FormModel { +class PersonalForm implements FormModel { PersonalForm( this.form, this.path, @@ -1001,7 +1001,7 @@ class PersonalForm implements FormModel { disabled: false); } -class PhoneForm implements FormModel { +class PhoneForm implements FormModel { PhoneForm( this.form, this.path, @@ -1309,7 +1309,7 @@ class PhoneForm implements FormModel { disabled: false); } -class AddressForm implements FormModel
{ +class AddressForm implements FormModel { AddressForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/login/login.gform.dart b/packages/reactive_forms_generator/example/lib/docs/login/login.gform.dart index 6ca84650..3364b1a2 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login/login.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login/login.gform.dart @@ -179,7 +179,7 @@ class _LoginFormBuilderState extends State { } } -class LoginForm implements FormModel { +class LoginForm implements FormModel { LoginForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/login/login_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/login/login_output.gform.dart index d5b8084f..38f41d88 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login/login_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login/login_output.gform.dart @@ -112,7 +112,7 @@ class LoginOFormBuilder extends StatefulWidget { this.initState, }) : super(key: key); - final LoginOOutput? model; + final LoginO? model; final Widget? child; @@ -191,7 +191,7 @@ class LoginOOutput extends Equatable { List get props => [email, password]; } -class LoginOForm implements FormModel { +class LoginOForm implements FormModel { LoginOForm( this.form, this.path, @@ -211,9 +211,9 @@ class LoginOForm implements FormModel { String passwordControlPath() => pathBuilder(passwordControlName); - String? get _emailValue => emailControl?.value; + String get _emailValue => emailControl.value as String; - String? get _passwordValue => passwordControl?.value; + String get _passwordValue => passwordControl.value as String; bool get containsEmail { try { @@ -233,9 +233,9 @@ class LoginOForm implements FormModel { } } - Map? get emailErrors => emailControl?.errors; + Map? get emailErrors => emailControl.errors; - Map? get passwordErrors => passwordControl?.errors; + Map? get passwordErrors => passwordControl.errors; void get emailFocus => form.focus(emailControlPath()); @@ -298,7 +298,7 @@ class LoginOForm implements FormModel { bool updateParent = true, bool emitEvent = true, }) { - emailControl?.updateValue(value, + emailControl.updateValue(value, updateParent: updateParent, emitEvent: emitEvent); } @@ -307,7 +307,7 @@ class LoginOForm implements FormModel { bool updateParent = true, bool emitEvent = true, }) { - passwordControl?.updateValue(value, + passwordControl.updateValue(value, updateParent: updateParent, emitEvent: emitEvent); } @@ -316,7 +316,7 @@ class LoginOForm implements FormModel { bool updateParent = true, bool emitEvent = true, }) { - emailControl?.patchValue(value, + emailControl.patchValue(value, updateParent: updateParent, emitEvent: emitEvent); } @@ -325,7 +325,7 @@ class LoginOForm implements FormModel { bool updateParent = true, bool emitEvent = true, }) { - passwordControl?.patchValue(value, + passwordControl.patchValue(value, updateParent: updateParent, emitEvent: emitEvent); } @@ -336,7 +336,7 @@ class LoginOForm implements FormModel { bool removeFocus = false, bool? disabled, }) => - emailControl?.reset( + emailControl.reset( value: value, updateParent: updateParent, emitEvent: emitEvent); void passwordValueReset( @@ -346,16 +346,14 @@ class LoginOForm implements FormModel { bool removeFocus = false, bool? disabled, }) => - passwordControl?.reset( + passwordControl.reset( value: value, updateParent: updateParent, emitEvent: emitEvent); - FormControl? get emailControl => containsEmail - ? form.control(emailControlPath()) as FormControl? - : null; + FormControl get emailControl => + form.control(emailControlPath()) as FormControl; - FormControl? get passwordControl => containsPassword - ? form.control(passwordControlPath()) as FormControl? - : null; + FormControl get passwordControl => + form.control(passwordControlPath()) as FormControl; void emailSetDisabled( bool disabled, { @@ -363,12 +361,12 @@ class LoginOForm implements FormModel { bool emitEvent = true, }) { if (disabled) { - emailControl?.markAsDisabled( + emailControl.markAsDisabled( updateParent: updateParent, emitEvent: emitEvent, ); } else { - emailControl?.markAsEnabled( + emailControl.markAsEnabled( updateParent: updateParent, emitEvent: emitEvent, ); @@ -381,12 +379,12 @@ class LoginOForm implements FormModel { bool emitEvent = true, }) { if (disabled) { - passwordControl?.markAsDisabled( + passwordControl.markAsDisabled( updateParent: updateParent, emitEvent: emitEvent, ); } else { - passwordControl?.markAsEnabled( + passwordControl.markAsEnabled( updateParent: updateParent, emitEvent: emitEvent, ); @@ -456,7 +454,7 @@ class LoginOForm implements FormModel { @override void updateValue( - LoginOOutput? value, { + LoginO? value, { bool updateParent = true, bool emitEvent = true, }) => @@ -465,7 +463,7 @@ class LoginOForm implements FormModel { @override void reset({ - LoginOOutput? value, + LoginO? value, bool updateParent = true, bool emitEvent = true, }) => @@ -477,7 +475,7 @@ class LoginOForm implements FormModel { String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); - static FormGroup formElements(LoginOOutput? loginO) => FormGroup({ + static FormGroup formElements(LoginO? loginO) => FormGroup({ emailControlName: FormControl( value: loginO?.email, validators: [RequiredValidator(), RequiredValidator()], diff --git a/packages/reactive_forms_generator/example/lib/docs/login/login_output_form.dart b/packages/reactive_forms_generator/example/lib/docs/login/login_output_form.dart new file mode 100644 index 00000000..0256c5e7 --- /dev/null +++ b/packages/reactive_forms_generator/example/lib/docs/login/login_output_form.dart @@ -0,0 +1,177 @@ +import 'package:example/docs/login/labels.dart'; +import 'package:example/docs/login/login_output.dart'; +import 'package:example/docs/login/mocks.dart'; +import 'package:example/sample_screen.dart'; +import 'package:flutter/material.dart' hide ProgressIndicator; +import 'package:reactive_forms_annotations/reactive_forms_annotations.dart'; + +class LoginOutputFormWidget extends StatefulWidget { + final ValueChanged? onChange; + + const LoginOutputFormWidget({super.key, this.onChange}); + + @override + State createState() => _LoginFormWidgetState(); +} + +class _LoginFormWidgetState extends State { + LoginO _emptyModel = mockedLoginOEmpty; + + @override + Widget build(BuildContext context) { + return SampleScreen( + title: const Text('Login Output(beta)'), + body: LoginOFormBuilder( + model: _emptyModel, + builder: (context, formModel, child) { + return Column( + children: [ + ReactiveTextField( + key: email.itemKey, + formControl: formModel.emailControl, + validationMessages: { + ValidationMessage.required: (_) => errorRequired + }, + decoration: InputDecoration( + labelText: email.name, + helperText: '', + helperStyle: const TextStyle(height: 0.8), + errorStyle: const TextStyle(height: 0.8), + ), + ), + const SizedBox(height: 8.0), + ReactiveTextField( + key: password.itemKey, + formControl: formModel.passwordControl, + obscureText: true, + validationMessages: { + ValidationMessage.required: (_) => errorRequired, + 'mustMatch': (_) => errorMustMatch, + }, + textInputAction: TextInputAction.done, + decoration: InputDecoration( + labelText: password.name, + helperText: '', + helperStyle: const TextStyle(height: 0.8), + errorStyle: const TextStyle(height: 0.8), + ), + ), + // ReactiveLoginFormConsumer( + // builder: (context, formModel, child) { + // // debugPrint(formModel.passwordControl.errors); + // // debugPrint(formModel.form); + // debugPrint('dirty => ${formModel.form.dirty}'); + // debugPrint( + // 'passwordDirty => ${formModel.passwordControl.dirty}'); + // + // return Column( + // children: [ + // Text(formModel.emailControl.errors.toString()), + // Text(formModel.passwordControl.errors.toString()), + // ], + // ); + // }, + // ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Expanded( + child: ElevatedButton( + key: submitRaw.itemKey, + onPressed: () { + debugPrint(formModel.model.email); + debugPrint(formModel.model.password); + formModel.form.markAllAsTouched(); + widget.onChange?.call(formModel.model); + }, + child: const Text('Submit raw'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ReactiveLoginOFormConsumer( + builder: (context, formModel, child) { + return ElevatedButton( + key: submit.itemKey, + onPressed: formModel.form.valid + ? () { + debugPrint(formModel.model.toString()); + debugPrint(formModel.model.email); + debugPrint(formModel.model.password); + widget.onChange?.call(formModel.model); + } + : null, + child: const Text('Submit'), + ); + }, + ), + ), + ], + ), + Row( + children: [ + Expanded( + child: ElevatedButton( + key: submitRaw.itemKey, + onPressed: () => formModel.submit( + onValid: (_) => debugPrint('FormValid'), + onNotValid: () { + debugPrint('FormInvalid'); + }, + ), + child: const Text('Submit method'), + ), + ), + const SizedBox(width: 8), + ], + ), + Row( + children: [ + Expanded( + child: ElevatedButton( + key: updateModel.itemKey, + onPressed: () { + setState(() => _emptyModel = mockedLoginO); + }, + child: const Text('Update model'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + key: reset.itemKey, + onPressed: () => formModel.reset(), + child: const Text('Reset'), + ), + ), + ], + ), + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () => + formModel.emailControl.markAsDisabled(), + child: const Text('Disable Email'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + onPressed: () => formModel.toggleDisabled(), + child: const Text('Toggle Disabled'), + ), + ), + ], + ), + ], + ), + ], + ); + }, + ), + ); + } +} diff --git a/packages/reactive_forms_generator/example/lib/docs/login/mocks.dart b/packages/reactive_forms_generator/example/lib/docs/login/mocks.dart index 66e08934..a8cee7a8 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login/mocks.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login/mocks.dart @@ -1,7 +1,10 @@ import 'package:example/docs/login/login.dart'; +import 'package:example/docs/login/login_output.dart'; const mockedLoginEmpty = Login(); +const mockedLoginOEmpty = LoginO(); const mockedLogin = Login(email: 'some@e.mail', password: 'xx'); +const mockedLoginO = LoginO(email: 'some@e.mail', password: 'xx'); const mockedLogin1 = Login(email: 'some@e.mail', password: 'some@e.mail'); diff --git a/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended.gform.dart b/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended.gform.dart index 5ae0dcfe..0d6c2b1b 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended.gform.dart @@ -185,7 +185,7 @@ class _LoginExtendedFormBuilderState extends State { } } -class LoginExtendedForm implements FormModel { +class LoginExtendedForm implements FormModel { LoginExtendedForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable.gform.dart b/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable.gform.dart index 5fe83d59..1b2df604 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable.gform.dart @@ -187,7 +187,8 @@ class _LoginExtendedNullableFormBuilderState } } -class LoginExtendedNullableForm implements FormModel { +class LoginExtendedNullableForm + implements FormModel { LoginExtendedNullableForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list.gform.dart b/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list.gform.dart index 7cd4c894..2539c06a 100644 --- a/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list.gform.dart @@ -183,7 +183,7 @@ class _MailingListFormBuilderState extends State { } } -class MailingListForm implements FormModel { +class MailingListForm implements FormModel { MailingListForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends.gform.dart b/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends.gform.dart index 128eb4a8..d82be75f 100644 --- a/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends.gform.dart @@ -185,7 +185,7 @@ class _ModelExtendsFormBuilderState extends State { } } -class ModelExtendsForm implements FormModel { +class ModelExtendsForm implements FormModel { ModelExtendsForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends_form.dart b/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends_form.dart index 4d05122f..d6ada5f6 100644 --- a/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends_form.dart +++ b/packages/reactive_forms_generator/example/lib/docs/model_extends/model_extends_form.dart @@ -102,7 +102,8 @@ class _ModelExtendsWidgetState extends State { onPressed: formModel.form.valid ? () { // ignore: unnecessary_cast, avoid_print - debugPrint((formModel as FormModel) + debugPrint((formModel + as FormModel) .model .toString()); // ignore: avoid_print diff --git a/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements.gform.dart b/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements.gform.dart index d051808c..b2e87b21 100644 --- a/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements.gform.dart @@ -188,7 +188,8 @@ class _ModelImplementsFormBuilderState } } -class ModelImplementsForm implements FormModel { +class ModelImplementsForm + implements FormModel { ModelImplementsForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements_form.dart b/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements_form.dart index 1ba9e09e..43f4c5c3 100644 --- a/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements_form.dart +++ b/packages/reactive_forms_generator/example/lib/docs/model_implements/model_implements_form.dart @@ -100,7 +100,8 @@ class _ModelImplementsWidgetState extends State { onPressed: formModel.form.valid ? () { // ignore: unnecessary_cast, avoid_print - debugPrint((formModel as FormModel) + debugPrint((formModel as FormModel) .model .toString()); // ignore: avoid_print diff --git a/packages/reactive_forms_generator/example/lib/docs/nested/nested.gform.dart b/packages/reactive_forms_generator/example/lib/docs/nested/nested.gform.dart index 822afd15..88a6e9b6 100644 --- a/packages/reactive_forms_generator/example/lib/docs/nested/nested.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/nested/nested.gform.dart @@ -180,7 +180,7 @@ class _SubGroupFormBuilderState extends State { } } -class SubGroupForm implements FormModel { +class SubGroupForm implements FormModel { SubGroupForm( this.form, this.path, @@ -663,7 +663,7 @@ class _GroupFormBuilderState extends State { } } -class GroupForm implements FormModel { +class GroupForm implements FormModel { GroupForm( this.form, this.path, @@ -1334,7 +1334,7 @@ class _NestedFormBuilderState extends State { } } -class NestedForm implements FormModel { +class NestedForm implements FormModel { NestedForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/profile/profile.gform.dart b/packages/reactive_forms_generator/example/lib/docs/profile/profile.gform.dart index a4815719..89fc6c0f 100644 --- a/packages/reactive_forms_generator/example/lib/docs/profile/profile.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/profile/profile.gform.dart @@ -179,7 +179,7 @@ class _ProfileFormBuilderState extends State { } } -class ProfileForm implements FormModel { +class ProfileForm implements FormModel { ProfileForm( this.form, this.path, @@ -1066,7 +1066,8 @@ class ProfileForm implements FormModel { disabled: false); } -class IncidenceFilterForm implements FormModel { +class IncidenceFilterForm + implements FormModel { IncidenceFilterForm( this.form, this.path, @@ -1641,7 +1642,8 @@ class IncidenceFilterForm implements FormModel { disabled: false); } -class ThresholdSettingForm implements FormModel { +class ThresholdSettingForm + implements FormModel { ThresholdSettingForm( this.form, this.path, @@ -1896,7 +1898,7 @@ class ThresholdSettingForm implements FormModel { disabled: false); } -class TimerSettingForm implements FormModel { +class TimerSettingForm implements FormModel { TimerSettingForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic.gform.dart b/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic.gform.dart index a768baf7..7c5f13e9 100644 --- a/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic.gform.dart @@ -185,7 +185,7 @@ class _SomeWiredNameFormBuilderState extends State { } } -class SomeWiredNameForm implements FormModel { +class SomeWiredNameForm implements FormModel { SomeWiredNameForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_form.dart b/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_form.dart index da09f9e1..d942e39a 100644 --- a/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_form.dart +++ b/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_form.dart @@ -51,7 +51,8 @@ class BasicFormWidget extends StatelessWidget { onPressed: formModel.form.valid ? () { // ignore: unnecessary_cast - debugPrint((formModel as FormModel) + debugPrint((formModel + as FormModel) .model .toString()); debugPrint(formModel.model.email); diff --git a/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile.gform.dart b/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile.gform.dart index 0ca7314a..c8f14c86 100644 --- a/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile.gform.dart @@ -183,7 +183,7 @@ class _UserProfileFormBuilderState extends State { } } -class UserProfileForm implements FormModel { +class UserProfileForm implements FormModel { UserProfileForm( this.form, this.path, @@ -692,7 +692,7 @@ class UserProfileForm implements FormModel { disabled: false); } -class AddressForm implements FormModel
{ +class AddressForm implements FormModel { AddressForm( this.form, this.path, diff --git a/packages/reactive_forms_generator/example/lib/drawer.dart b/packages/reactive_forms_generator/example/lib/drawer.dart index 0d965cc7..a0da9769 100644 --- a/packages/reactive_forms_generator/example/lib/drawer.dart +++ b/packages/reactive_forms_generator/example/lib/drawer.dart @@ -17,6 +17,12 @@ class AppDrawer extends StatelessWidget { Routes.login, ), ), + ListTile( + title: const Text('LoginOutput(beta)'), + onTap: () => Navigator.of(context).pushReplacementNamed( + Routes.loginOutput, + ), + ), ListTile( title: const Text('Annotateless'), onTap: () => Navigator.of(context).pushReplacementNamed( diff --git a/packages/reactive_forms_generator/example/lib/main.dart b/packages/reactive_forms_generator/example/lib/main.dart index 26ecef7d..944220b2 100644 --- a/packages/reactive_forms_generator/example/lib/main.dart +++ b/packages/reactive_forms_generator/example/lib/main.dart @@ -7,6 +7,7 @@ import 'package:example/docs/freezed/freezed_form.dart'; import 'package:example/docs/generic/generic_form.dart'; import 'package:example/docs/group/group_form.dart'; import 'package:example/docs/login/login_form.dart'; +import 'package:example/docs/login/login_output_form.dart'; import 'package:example/docs/login_extended/login_extended_form.dart'; import 'package:example/docs/login_extended_nullable/login_extended_nullable_form.dart'; import 'package:example/docs/mailing_list/mailing_list_form.dart'; @@ -34,6 +35,7 @@ class MyApp extends StatelessWidget { routes: { Routes.loginExtended: (_) => const LoginExtendedFormWidget(), Routes.login: (_) => const LoginFormWidget(), + Routes.loginOutput: (_) => const LoginOutputFormWidget(), Routes.annotateless: (_) => const AnnotatelessFormWidget(), Routes.mailingList: (_) => const MailingListFormWidget(), Routes.userProfile: (_) => const UserProfileFormWidget(), @@ -60,6 +62,8 @@ class Routes { static const login = '/login'; + static const loginOutput = '/login-output'; + static const annotateless = '/annotateless'; static const mailingList = '/mailing-list'; diff --git a/packages/reactive_forms_generator/lib/src/extensions.dart b/packages/reactive_forms_generator/lib/src/extensions.dart index ff563c85..6b2f282f 100644 --- a/packages/reactive_forms_generator/lib/src/extensions.dart +++ b/packages/reactive_forms_generator/lib/src/extensions.dart @@ -14,7 +14,10 @@ extension ConstructorElementExt on ConstructorElement { } extension ClassElementExt on ClassElement { - String get fullTypeName => '${thisType.toString()}${output ? 'Output' : ''}'; + String get fullTypeName => thisType.toString(); + + String get fullTypeNameOutput => + '${thisType.toString()}${output ? 'Output' : ''}'; String get generics { final generics = genericTypes.map((e) => e.symbol).join(', '); diff --git a/packages/reactive_forms_generator/lib/src/form_elements/form_element_generator.dart b/packages/reactive_forms_generator/lib/src/form_elements/form_element_generator.dart index da0fd90c..4cef573f 100644 --- a/packages/reactive_forms_generator/lib/src/form_elements/form_element_generator.dart +++ b/packages/reactive_forms_generator/lib/src/form_elements/form_element_generator.dart @@ -7,14 +7,14 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/types.dart'; import 'package:source_gen/source_gen.dart'; import 'package:recase/recase.dart'; -import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/dart/ast/ast.dart'; abstract class FormElementGenerator { final ClassElement root; final ParameterElement field; final DartType? type; + static const String validatorKey = 'validators'; + FormElementGenerator(this.root, this.field, this.type); String get value { @@ -93,7 +93,9 @@ abstract class FormElementGenerator { // } String get validators => - fieldElement.annotationParams(typeChecker)['validators'] ?? '[]'; + fieldElement + .annotationParams(typeChecker)[FormElementGenerator.validatorKey] ?? + '[]'; String get itemAsyncValidators => fieldElement.annotationParams(typeChecker)['itemAsyncValidators'] ?? '[]'; diff --git a/packages/reactive_forms_generator/lib/src/form_generator.dart b/packages/reactive_forms_generator/lib/src/form_generator.dart index 14e5eb89..2c247fdf 100644 --- a/packages/reactive_forms_generator/lib/src/form_generator.dart +++ b/packages/reactive_forms_generator/lib/src/form_generator.dart @@ -1,6 +1,4 @@ // ignore_for_file: implementation_imports -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; @@ -431,7 +429,7 @@ class FormGenerator { b ..name = 'model' - ..returns = Reference(element.fullTypeName) + ..returns = Reference(element.fullTypeNameOutput) ..annotations.add(const CodeExpression(Code('override'))) ..type = MethodType.getter ..body = Code(''' @@ -440,7 +438,7 @@ class FormGenerator { if (!isValid) { debugPrintStack(label: '[\${path ?? '$classNameFull'}]\\nā”—ā” Avoid calling `model` on invalid form. Possible exceptions for non-nullable fields which should be guarded by `required` validator.'); } - return ${element.fullTypeName}(${parameterValues.join(', ')}); + return ${element.fullTypeNameOutput}(${parameterValues.join(', ')}); '''); }, ); @@ -553,7 +551,7 @@ class FormGenerator { ..named = true ..required = true ..type = Reference( - 'void Function(${element.fullTypeName} model)'), + 'void Function(${element.fullTypeNameOutput} model)'), ), Parameter( (b) => b @@ -651,7 +649,8 @@ class FormGenerator { (b) => b ..name = className ..types.addAll(element.fullGenericTypes) - ..implements.add(Reference('FormModel<${element.fullTypeName}>')) + ..implements.add(Reference( + 'FormModel<${element.fullTypeName}, ${element.fullTypeNameOutput}>')) ..fields.addAll( [ ...staticFieldNameList, @@ -826,57 +825,70 @@ class FormGenerator { ); } - Iterable get fieldContainsMethodList => - all.map((e) => ContainsMethod(e).method()).whereType(); + Iterable get fieldContainsMethodList => all + .map((e) => ContainsMethod(e, element.output).method()) + .whereType(); - Iterable get fieldValueMethodList => - all.map((e) => FieldValueMethod(e).method()).whereType(); + Iterable get fieldValueMethodList => all + .map((e) => FieldValueMethod(e, element.output).method()) + .whereType(); - Iterable get fieldControlNameMethodList => - all.map((e) => ControlPathMethod(e).method()).whereType(); + Iterable get fieldControlNameMethodList => all + .map((e) => ControlPathMethod(e, element.output).method()) + .whereType(); Iterable get staticFieldNameList => annotatedParameters.map(staticFieldName); - Iterable get fieldErrorsMethodList => - all.map((e) => ErrorsMethod(e).method()).whereType(); + Iterable get fieldErrorsMethodList => all + .map((e) => ErrorsMethod(e, element.output).method()) + .whereType(); Iterable get fieldNameList => annotatedParameters.map(field); - Iterable get fieldFocusMethodList => - all.map((e) => FocusMethod(e).method()).whereType(); + Iterable get fieldFocusMethodList => all + .map((e) => FocusMethod(e, element.output).method()) + .whereType(); - Iterable get fieldRemoveMethodList => - all.map((e) => RemoveMethod(e).method()).whereType(); + Iterable get fieldRemoveMethodList => all + .map((e) => RemoveMethod(e, element.output).method()) + .whereType(); Iterable get fieldUpdateMethodList => all - .map((e) => ReactiveFormUpdateValueMethod(e).method()) + .map((e) => ReactiveFormUpdateValueMethod(e, element.output).method()) .whereType(); - Iterable get fieldInsertMethodList => - all.map((e) => ReactiveFormInsertMethod(e).method()).whereType(); + Iterable get fieldInsertMethodList => all + .map((e) => ReactiveFormInsertMethod(e, element.output).method()) + .whereType(); - Iterable get fieldClearMethodList => - all.map((e) => ReactiveFormClearMethod(e).method()).whereType(); + Iterable get fieldClearMethodList => all + .map((e) => ReactiveFormClearMethod(e, element.output).method()) + .whereType(); Iterable get fieldPatchMethodList => all - .map((e) => ReactiveFormPatchValueMethod(e).method()) + .map((e) => ReactiveFormPatchValueMethod(e, element.output).method()) .whereType(); - Iterable get fieldResetMethodList => - all.map((e) => ResetMethod(e).method()).whereType(); + Iterable get fieldResetMethodList => all + .map((e) => ResetMethod(e, element.output).method()) + .whereType(); - Iterable get controlMethodList => - all.map((e) => ControlMethod(e).method()).whereType(); + Iterable get controlMethodList => all + .map((e) => ControlMethod(e, element.output).method()) + .whereType(); - Iterable get controlPrivateMethodList => - all.map((e) => ControlPrivateMethod(e).method()).whereType(); + Iterable get controlPrivateMethodList => all + .map((e) => ControlPrivateMethod(e, element.output).method()) + .whereType(); - Iterable get controlSetDisabledMethodList => - all.map((e) => ControlSetDisableMethod(e).method()).whereType(); + Iterable get controlSetDisabledMethodList => all + .map((e) => ControlSetDisableMethod(e, element.output).method()) + .whereType(); - Iterable get extendedControlMethodList => - all.map((e) => ExtendedControlMethod(e).method()).whereType(); + Iterable get extendedControlMethodList => all + .map((e) => ExtendedControlMethod(e, element.output).method()) + .whereType(); Iterable get addArrayControlMethodList => formArrays.map(addArrayControl); diff --git a/packages/reactive_forms_generator/lib/src/library_builder.dart b/packages/reactive_forms_generator/lib/src/library_builder.dart index 2fe8c2d6..f2531a93 100644 --- a/packages/reactive_forms_generator/lib/src/library_builder.dart +++ b/packages/reactive_forms_generator/lib/src/library_builder.dart @@ -10,7 +10,6 @@ import 'package:reactive_forms_generator/src/reactive_forms/reactive_form_consum import 'package:reactive_forms_generator/src/reactive_forms/reactive_form_extension.dart'; import 'package:reactive_forms_generator/src/reactive_forms/reactive_form_group_array_builder.dart'; import 'package:reactive_forms_generator/src/reactive_forms/reactive_inherited_streamer.dart'; -import 'package:reactive_forms_generator/src/types.dart'; const stringRef = Reference('String'); const formGroupRef = Reference('FormGroup'); diff --git a/packages/reactive_forms_generator/lib/src/reactive_form_generator_method.dart b/packages/reactive_forms_generator/lib/src/reactive_form_generator_method.dart index d5f6dc94..26d5826e 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_form_generator_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_form_generator_method.dart @@ -1,11 +1,13 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:code_builder/code_builder.dart'; import 'package:reactive_forms_generator/src/extensions.dart'; +import 'package:reactive_forms_generator/src/types.dart'; abstract class ReactiveFormGeneratorMethod { final ParameterElement field; + final bool output; - ReactiveFormGeneratorMethod(this.field); + ReactiveFormGeneratorMethod(this.field, this.output); Method? method() { if (field.isFormGroup) { @@ -23,6 +25,23 @@ abstract class ReactiveFormGeneratorMethod { return formControlMethod(); } + bool get toOutput { + if (field.isFormGroup) { + return false; + } + + if (field.isFormArray) { + return false; + } + + if (field.isFormGroupArray) { + return false; + } + + return field.annotationParams(formControlChecker).hasRequiredValidator && + output; + } + Method? formControlMethod() => defaultMethod(); Method? formGroupMethod() => defaultMethod(); diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_update_value_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_update_value_method.dart index 90e7885d..0a4591db 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_update_value_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_update_value_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ReactiveFormUpdateValueMethod extends ReactiveFormGeneratorMethod { - ReactiveFormUpdateValueMethod(super.field); + ReactiveFormUpdateValueMethod(super.field, super.output); @override Method formGroupArrayMethod() { @@ -60,7 +60,7 @@ class ReactiveFormUpdateValueMethod extends ReactiveFormGeneratorMethod { Method defaultMethod() { return methodEntity.rebuild( (b) => b.body = Code( - '${field.fieldControlName}${field.nullabilitySuffix}.updateValue(value, updateParent: updateParent, emitEvent:emitEvent);', + '${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.updateValue(value, updateParent: updateParent, emitEvent:emitEvent);', ), ); } diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_clear_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_clear_method.dart index 2025476f..f7f0fe35 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_clear_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_clear_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ReactiveFormClearMethod extends ReactiveFormGeneratorMethod { - ReactiveFormClearMethod(super.field); + ReactiveFormClearMethod(super.field, super.output); @override Method? formGroupArrayMethod() { diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_insert_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_insert_method.dart index 07c782f3..3d320685 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_insert_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_insert_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ReactiveFormInsertMethod extends ReactiveFormGeneratorMethod { - ReactiveFormInsertMethod(super.field); + ReactiveFormInsertMethod(super.field, super.output); @override Method? formGroupArrayMethod() { diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_patch_value_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_patch_value_method.dart index 36043b88..ad417a32 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_patch_value_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_forms_patch_value_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ReactiveFormPatchValueMethod extends ReactiveFormGeneratorMethod { - ReactiveFormPatchValueMethod(super.field); + ReactiveFormPatchValueMethod(super.field, super.output); @override Method formGroupArrayMethod() { @@ -42,7 +42,7 @@ class ReactiveFormPatchValueMethod extends ReactiveFormGeneratorMethod { Method defaultMethod() { return methodEntity.rebuild( (b) => b.body = Code( - '${field.fieldControlName}${field.nullabilitySuffix}.patchValue(value, updateParent: updateParent, emitEvent:emitEvent);', + '${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.patchValue(value, updateParent: updateParent, emitEvent:emitEvent);', ), ); } diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/contains_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/contains_method.dart index fe1ea878..3adf9cd8 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/contains_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/contains_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ContainsMethod extends ReactiveFormGeneratorMethod { - ContainsMethod(super.field); + ContainsMethod(super.field, super.output); @override Method? defaultMethod() => Method( diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_method.dart index 7c5cf6d3..a88c9483 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_method.dart @@ -5,7 +5,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ControlMethod extends ReactiveFormGeneratorMethod { - ControlMethod(super.field); + ControlMethod(super.field, super.output); @override Method? formGroupMethod() { @@ -97,19 +97,22 @@ class ControlMethod extends ReactiveFormGeneratorMethod { @override Method? formControlMethod() { - String displayType = field.type.getDisplayString(withNullability: true); + String displayType = + field.type.getDisplayString(withNullability: !toOutput); // we need to trim last NullabilitySuffix.question cause FormControl modifies // generic T => T? - if (field.type.nullabilitySuffix == NullabilitySuffix.question) { + if (field.type.nullabilitySuffix == NullabilitySuffix.question && + !toOutput) { displayType = displayType.substring(0, displayType.length - 1); } - final reference = 'FormControl<$displayType>${field.nullabilitySuffix}'; + final reference = + 'FormControl<$displayType>${toOutput ? '' : field.nullabilitySuffix}'; String body = 'form.control(${field.fieldControlPath}()) as $reference'; - if (field.isNullable) { + if (field.isNullable && !toOutput) { body = '${field.containsMethodName} ? form.control(${field.fieldControlPath}()) as $reference : null'; } diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_path_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_path_method.dart index a8cf0336..fd3c5bf4 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_path_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_path_method.dart @@ -4,7 +4,7 @@ import 'package:reactive_forms_generator/src/library_builder.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ControlPathMethod extends ReactiveFormGeneratorMethod { - ControlPathMethod(super.field); + ControlPathMethod(super.field, super.output); @override Method? defaultMethod() => Method( diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_private_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_private_method.dart index 0293ae28..99d8c455 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_private_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_private_method.dart @@ -5,7 +5,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ControlPrivateMethod extends ReactiveFormGeneratorMethod { - ControlPrivateMethod(super.field); + ControlPrivateMethod(super.field, super.output); @override Method? formGroupMethod() { diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_set_enabled_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_set_enabled_method.dart index 0ff4e799..8bb3a308 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_set_enabled_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/control_set_enabled_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ControlSetDisableMethod extends ReactiveFormGeneratorMethod { - ControlSetDisableMethod(super.field); + ControlSetDisableMethod(super.field, super.output); @override Method? defaultMethod() { @@ -12,13 +12,13 @@ class ControlSetDisableMethod extends ReactiveFormGeneratorMethod { ..body = Code( ''' if(disabled) { - ${field.fieldControlName}${field.nullabilitySuffix}.markAsDisabled( + ${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.markAsDisabled( updateParent: updateParent, emitEvent: emitEvent, ); } else { - ${field.fieldControlName}${field.nullabilitySuffix}.markAsEnabled( + ${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.markAsEnabled( updateParent: updateParent, emitEvent: emitEvent, ); diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/errors_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/errors_method.dart index 1929568a..9bb1975c 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/errors_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/errors_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ErrorsMethod extends ReactiveFormGeneratorMethod { - ErrorsMethod(super.field); + ErrorsMethod(super.field, super.output); @override Method? defaultMethod() => Method( @@ -13,7 +13,7 @@ class ErrorsMethod extends ReactiveFormGeneratorMethod { ..type = MethodType.getter ..returns = Reference('Map${field.nullabilitySuffix}') ..body = Code( - '${field.fieldControlName}${field.nullabilitySuffix}.errors', + '${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.errors', ), ); } diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/extended_control_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/extended_control_method.dart index 8b0164b1..7b6e64dd 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/extended_control_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/extended_control_method.dart @@ -4,7 +4,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ExtendedControlMethod extends ReactiveFormGeneratorMethod { - ExtendedControlMethod(super.field); + ExtendedControlMethod(super.field, super.output); @override Method? formGroupArrayMethod() { diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart index e8bba644..682af825 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart @@ -3,10 +3,9 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:code_builder/code_builder.dart'; import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; -import 'package:reactive_forms_generator/src/types.dart'; class FieldValueMethod extends ReactiveFormGeneratorMethod { - FieldValueMethod(super.field); + FieldValueMethod(super.field, super.output); @override Method? formGroupMethod() { @@ -39,14 +38,14 @@ class FieldValueMethod extends ReactiveFormGeneratorMethod { @override Method? defaultMethod() { - final x = field.annotationParams(formControlChecker); - - String code = '${field.fieldControlName}${field.nullabilitySuffix}.value'; - String codeTypeCast = ' as ${field.type}'; + String code = + '${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.value'; + String codeTypeCast = + ' as ${field.type.getDisplayString(withNullability: !toOutput)}'; // do not add additional cast if the field is nullable to avoid // unnecessary_cast notes - if (field.type.nullabilitySuffix == NullabilitySuffix.none) { + if (field.type.nullabilitySuffix == NullabilitySuffix.none || toOutput) { if (field.hasDefaultValue) { final constantValueObject = field.computeConstantValue(); if (constantValueObject?.type?.isDartCoreString ?? false) { @@ -70,6 +69,8 @@ class FieldValueMethod extends ReactiveFormGeneratorMethod { ..name = field.fieldValueName ..lambda = true ..type = MethodType.getter - ..returns = Reference(field.type.toString()), + ..returns = Reference( + field.type.getDisplayString(withNullability: !toOutput), + ), ); } diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/focus_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/focus_method.dart index 73f453cc..d3757a8d 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/focus_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/focus_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class FocusMethod extends ReactiveFormGeneratorMethod { - FocusMethod(super.field); + FocusMethod(super.field, super.output); @override Method? defaultMethod() => Method( diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/remove_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/remove_method.dart index 1b800173..9a63b8e4 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/remove_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/remove_method.dart @@ -4,7 +4,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class RemoveMethod extends ReactiveFormGeneratorMethod { - RemoveMethod(super.field); + RemoveMethod(super.field, super.output); @override Method? defaultMethod() { diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/reset_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/reset_method.dart index d927d533..c9d9af14 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/reset_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/reset_method.dart @@ -3,7 +3,7 @@ import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; class ResetMethod extends ReactiveFormGeneratorMethod { - ResetMethod(super.field); + ResetMethod(super.field, super.output); @override Method? formGroupArrayMethod() { @@ -40,7 +40,7 @@ class ResetMethod extends ReactiveFormGeneratorMethod { return methodEntity.rebuild( (b) => b ..body = Code( - '''${field.fieldControlName}${field.nullabilitySuffix}.reset( + '''${field.fieldControlName}${toOutput ? '' : field.nullabilitySuffix}.reset( value: value, updateParent: updateParent, emitEvent:emitEvent) diff --git a/packages/reactive_forms_generator/lib/src/types.dart b/packages/reactive_forms_generator/lib/src/types.dart index 07ef2981..858fe495 100644 --- a/packages/reactive_forms_generator/lib/src/types.dart +++ b/packages/reactive_forms_generator/lib/src/types.dart @@ -1,5 +1,6 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:reactive_forms_generator/src/form_elements/form_element_generator.dart'; import 'package:source_gen/source_gen.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; @@ -26,6 +27,15 @@ extension LibraryReaderExt on LibraryReader { } } +extension MapExt on Map { + bool get hasRequiredValidator { + return containsKey(FormElementGenerator.validatorKey) && + this[FormElementGenerator.validatorKey] + ?.contains('RequiredValidator()') == + true; + } +} + extension ElementRfExt on Element { bool get hasRfGroupAnnotation { return formGroupChecker.hasAnnotationOfExact(this); diff --git a/packages/reactive_forms_generator/pubspec.yaml b/packages/reactive_forms_generator/pubspec.yaml index 634bc632..e946eaa8 100644 --- a/packages/reactive_forms_generator/pubspec.yaml +++ b/packages/reactive_forms_generator/pubspec.yaml @@ -15,7 +15,7 @@ repository: https://github.com/artflutter/reactive_forms_generator # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 5.0.1 +version: 6.0.0-beta.0 environment: sdk: ">=3.0.0 <4.0.0"