From 2bf66460af2489d4db04135144297ba1ffd0535c Mon Sep 17 00:00:00 2001 From: Vasiliy Ditsyak Date: Wed, 15 Apr 2026 19:37:48 +0200 Subject: [PATCH] has changes fix --- .../doc/animated_url_list_output_test.dart | 172 +++----- .../test/doc/animated_url_list_test.dart | 170 +++---- .../test/doc/annotateless_output_test.dart | 88 ++-- .../test/doc/annotateless_test.dart | 89 ++-- .../lib/src/form_model.dart | 23 +- .../reactive_forms_generator/CHANGELOG.md | 4 + .../example/android/app/build.gradle | 6 +- .../example/android/build.gradle | 12 - .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../example/android/settings.gradle | 3 +- .../animated_url_list.gform.dart | 170 +++---- .../animated_url_list_output.gform.dart | 172 +++----- .../docs/annotateless/annotateless.gform.dart | 89 ++-- .../annotateless_output.gform.dart | 88 ++-- .../array_nullable/array_nullable.gform.dart | 88 ++-- .../array_nullable_output.gform.dart | 88 ++-- .../lib/docs/create/create_output.gform.dart | 330 +++++--------- .../delivery_list/delivery_list.gform.dart | 414 ++++++------------ .../delivery_list_output.gform.dart | 413 ++++++----------- .../delivery_list/delivery_route_form.dart | 29 +- .../lib/docs/freezed/freezed_class.gform.dart | 89 ++-- .../freezed/freezed_class_output.gform.dart | 88 ++-- .../example/lib/docs/freezed2/test.gform.dart | 88 ++-- .../lib/docs/generic/generic.gform.dart | 82 ++-- .../docs/generic/generic_output.gform.dart | 82 ++-- .../generic_status_list.gform.dart | 89 ++-- .../generic_status_list_output.gform.dart | 89 ++-- .../example/lib/docs/group/group.gform.dart | 319 +++++--------- .../lib/docs/group/group_output.gform.dart | 324 +++++--------- .../lib/docs/issue_203/issue_203.gform.dart | 88 ++-- .../example/lib/docs/login/login.gform.dart | 88 ++-- .../lib/docs/login/login_output.gform.dart | 88 ++-- .../login_extended/login_extended.gform.dart | 88 ++-- .../login_extended_output.gform.dart | 88 ++-- .../login_extended_nullable.gform.dart | 88 ++-- .../login_extended_nullable_output.gform.dart | 88 ++-- .../docs/mailing_list/mailing_list.gform.dart | 89 ++-- .../mailing_list_output.gform.dart | 89 ++-- .../model_extends/model_extends.gform.dart | 89 ++-- .../model_implements.gform.dart | 88 ++-- .../example/lib/docs/nested/nested.gform.dart | 258 ++++------- .../lib/docs/nested/nested_output.gform.dart | 257 ++++------- .../nested_generics.gform.dart | 170 +++---- .../nested_generics_output.gform.dart | 170 +++---- .../lib/docs/profile/profile.gform.dart | 332 +++++--------- .../docs/profile/profile_output.gform.dart | 331 +++++--------- .../lib/docs/recursive/recursive.gform.dart | 256 ++++------- .../renamed_basic/renamed_basic.gform.dart | 88 ++-- .../renamed_basic_output.gform.dart | 88 ++-- .../docs/user_profile/user_profile.gform.dart | 166 +++---- .../user_profile_output.gform.dart | 166 +++---- .../example/lib/widgets/dirty_badge.dart | 28 ++ .../delivery_list_dirty_test.dart | 215 +++++++++ .../lib/src/form_generator.dart | 127 +++--- .../reactive_forms/reactive_form_builder.dart | 8 +- .../reactive_forms_generator/pubspec.yaml | 2 +- 56 files changed, 2830 insertions(+), 4503 deletions(-) create mode 100644 packages/reactive_forms_generator/example/lib/widgets/dirty_badge.dart create mode 100644 packages/reactive_forms_generator/example/test/doc/delivery_list/delivery_list_dirty_test.dart diff --git a/packages/generator_tests/test/doc/animated_url_list_output_test.dart b/packages/generator_tests/test/doc/animated_url_list_output_test.dart index e5f771b4..7a70011e 100644 --- a/packages/generator_tests/test/doc/animated_url_list_output_test.dart +++ b/packages/generator_tests/test/doc/animated_url_list_output_test.dart @@ -202,6 +202,7 @@ class _AnimatedUrlLisOFormBuilderState AnimatedUrlLisOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -244,7 +245,9 @@ class _AnimatedUrlLisOFormBuilderState @override void didUpdateWidget(covariant AnimatedUrlLisOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -280,8 +283,12 @@ final _logAnimatedUrlLisOForm = Logger.detached('AnimatedUrlLisOForm'); class AnimatedUrlLisOForm implements FormModel { - AnimatedUrlLisOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnimatedUrlLisOForm( + this.form, + this.path, + this._formModel, { + AnimatedUrlLisO? initialModel, + }) : _ownInitialModel = initialModel; static const String urlListControlName = "urlList"; @@ -294,8 +301,10 @@ class AnimatedUrlLisOForm final Map _disabled = {}; - @override - final Map initial; + AnimatedUrlLisO? _ownInitialModel; + + late Map _ownInitialRawValue = + AnimatedUrlLisOForm.formElements(_ownInitialModel).rawValue; String urlListControlPath() => pathBuilder(urlListControlName); @@ -556,10 +565,28 @@ class AnimatedUrlLisOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AnimatedUrlLisO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AnimatedUrlLisO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnimatedUrlLisOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -598,55 +625,6 @@ class AnimatedUrlLisOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -672,8 +650,12 @@ class AnimatedUrlLisOForm final _logUrlEntityOForm = Logger.detached('UrlEntityOForm'); class UrlEntityOForm implements FormModel { - UrlEntityOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UrlEntityOForm( + this.form, + this.path, + this._formModel, { + UrlEntityO? initialModel, + }) : _ownInitialModel = initialModel; static const String labelControlName = "label"; @@ -688,8 +670,11 @@ class UrlEntityOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UrlEntityO? _ownInitialModel; + + late Map _ownInitialRawValue = UrlEntityOForm.formElements( + _ownInitialModel, + ).rawValue; String labelControlPath() => pathBuilder(labelControlName); @@ -967,10 +952,28 @@ class UrlEntityOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UrlEntityO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UrlEntityO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UrlEntityOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1009,55 +1012,6 @@ class UrlEntityOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/animated_url_list_test.dart b/packages/generator_tests/test/doc/animated_url_list_test.dart index e99d5e9e..688ba478 100644 --- a/packages/generator_tests/test/doc/animated_url_list_test.dart +++ b/packages/generator_tests/test/doc/animated_url_list_test.dart @@ -202,6 +202,7 @@ class _AnimatedUrlListFormBuilderState AnimatedUrlListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -244,7 +245,9 @@ class _AnimatedUrlListFormBuilderState @override void didUpdateWidget(covariant AnimatedUrlListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -280,8 +283,12 @@ final _logAnimatedUrlListForm = Logger.detached('AnimatedUrlListForm'); class AnimatedUrlListForm implements FormModel { - AnimatedUrlListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnimatedUrlListForm( + this.form, + this.path, + this._formModel, { + AnimatedUrlList? initialModel, + }) : _ownInitialModel = initialModel; static const String urlListControlName = "urlList"; @@ -294,8 +301,10 @@ class AnimatedUrlListForm final Map _disabled = {}; - @override - final Map initial; + AnimatedUrlList? _ownInitialModel; + + late Map _ownInitialRawValue = + AnimatedUrlListForm.formElements(_ownInitialModel).rawValue; String urlListControlPath() => pathBuilder(urlListControlName); @@ -555,10 +564,28 @@ class AnimatedUrlListForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AnimatedUrlList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AnimatedUrlList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnimatedUrlListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -597,55 +624,6 @@ class AnimatedUrlListForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -671,8 +649,12 @@ class AnimatedUrlListForm final _logUrlEntityForm = Logger.detached('UrlEntityForm'); class UrlEntityForm implements FormModel { - UrlEntityForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UrlEntityForm( + this.form, + this.path, + this._formModel, { + UrlEntity? initialModel, + }) : _ownInitialModel = initialModel; static const String labelControlName = "label"; @@ -687,8 +669,11 @@ class UrlEntityForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UrlEntity? _ownInitialModel; + + late Map _ownInitialRawValue = UrlEntityForm.formElements( + _ownInitialModel, + ).rawValue; String labelControlPath() => pathBuilder(labelControlName); @@ -919,10 +904,26 @@ class UrlEntityForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UrlEntity? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UrlEntity? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UrlEntityForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -961,55 +962,6 @@ class UrlEntityForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/annotateless_output_test.dart b/packages/generator_tests/test/doc/annotateless_output_test.dart index daba54fc..089d0790 100644 --- a/packages/generator_tests/test/doc/annotateless_output_test.dart +++ b/packages/generator_tests/test/doc/annotateless_output_test.dart @@ -192,6 +192,7 @@ class _AnnotatelessOFormBuilderState extends State { AnnotatelessOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -234,7 +235,9 @@ class _AnnotatelessOFormBuilderState extends State { @override void didUpdateWidget(covariant AnnotatelessOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -270,8 +273,12 @@ final _logAnnotatelessOForm = Logger.detached('AnnotatelessOForm'); class AnnotatelessOForm implements FormModel { - AnnotatelessOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnnotatelessOForm( + this.form, + this.path, + this._formModel, { + AnnotatelessO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -286,8 +293,10 @@ class AnnotatelessOForm final Map _disabled = {}; - @override - final Map initial; + AnnotatelessO? _ownInitialModel; + + late Map _ownInitialRawValue = + AnnotatelessOForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -519,10 +528,28 @@ class AnnotatelessOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AnnotatelessO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AnnotatelessO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnnotatelessOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -561,55 +588,6 @@ class AnnotatelessOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/annotateless_test.dart b/packages/generator_tests/test/doc/annotateless_test.dart index 93256827..bbba91da 100644 --- a/packages/generator_tests/test/doc/annotateless_test.dart +++ b/packages/generator_tests/test/doc/annotateless_test.dart @@ -189,6 +189,7 @@ class _AnnotatelessFormBuilderState extends State { AnnotatelessForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -231,7 +232,9 @@ class _AnnotatelessFormBuilderState extends State { @override void didUpdateWidget(covariant AnnotatelessFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -266,8 +269,12 @@ class _AnnotatelessFormBuilderState extends State { final _logAnnotatelessForm = Logger.detached('AnnotatelessForm'); class AnnotatelessForm implements FormModel { - AnnotatelessForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnnotatelessForm( + this.form, + this.path, + this._formModel, { + Annotateless? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -282,8 +289,11 @@ class AnnotatelessForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Annotateless? _ownInitialModel; + + late Map _ownInitialRawValue = AnnotatelessForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -514,10 +524,28 @@ class AnnotatelessForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Annotateless? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Annotateless? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnnotatelessForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -556,55 +584,6 @@ class AnnotatelessForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_annotations/lib/src/form_model.dart b/packages/reactive_forms_annotations/lib/src/form_model.dart index 0c718912..f0528d4f 100644 --- a/packages/reactive_forms_annotations/lib/src/form_model.dart +++ b/packages/reactive_forms_annotations/lib/src/form_model.dart @@ -12,13 +12,13 @@ abstract class FormModel { final String? path; - final Map? initial = null; - @protected TModelOutput get model; TModel get rawModel; + Map get initialRawValue; + void submit({ required void Function(TModelOutput model) onValid, void Function()? onNotValid, @@ -44,7 +44,22 @@ abstract class FormModel { reset({TModel? value, bool updateParent = true, bool emitEvent = true}); - void updateInitial(Map? value, String? path); - void toggleDisabled({bool updateParent = true, bool emitEvent = true}); + + static Object? sliceByPath(Object? root, String? path) { + if (path == null || path.isEmpty) return root; + Object? current = root; + for (final key in path.split('.')) { + if (current is Map) { + current = current[key]; + } else if (current is List) { + final idx = int.tryParse(key); + if (idx == null || idx < 0 || idx >= current.length) return null; + current = current[idx]; + } else { + return null; + } + } + return current; + } } diff --git a/packages/reactive_forms_generator/CHANGELOG.md b/packages/reactive_forms_generator/CHANGELOG.md index f8f9dbc0..1fdc9fa0 100644 --- a/packages/reactive_forms_generator/CHANGELOG.md +++ b/packages/reactive_forms_generator/CHANGELOG.md @@ -1,3 +1,7 @@ +## [8.4.0] + +* fix hasChanges + ## [8.3.1] * fix deps diff --git a/packages/reactive_forms_generator/example/android/app/build.gradle b/packages/reactive_forms_generator/example/android/app/build.gradle index 118ee1d9..deca80b7 100644 --- a/packages/reactive_forms_generator/example/android/app/build.gradle +++ b/packages/reactive_forms_generator/example/android/app/build.gradle @@ -28,12 +28,12 @@ android { ndkVersion flutter.ndkVersion compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '17' } sourceSets { diff --git a/packages/reactive_forms_generator/example/android/build.gradle b/packages/reactive_forms_generator/example/android/build.gradle index e83fb5da..bc157bd1 100644 --- a/packages/reactive_forms_generator/example/android/build.gradle +++ b/packages/reactive_forms_generator/example/android/build.gradle @@ -1,15 +1,3 @@ -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - allprojects { repositories { google() diff --git a/packages/reactive_forms_generator/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/reactive_forms_generator/example/android/gradle/wrapper/gradle-wrapper.properties index 3c472b99..aa49780c 100644 --- a/packages/reactive_forms_generator/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/reactive_forms_generator/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip diff --git a/packages/reactive_forms_generator/example/android/settings.gradle b/packages/reactive_forms_generator/example/android/settings.gradle index 7cd71285..e47c1507 100644 --- a/packages/reactive_forms_generator/example/android/settings.gradle +++ b/packages/reactive_forms_generator/example/android/settings.gradle @@ -23,7 +23,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false + id "com.android.application" version "8.2.1" apply false + id "org.jetbrains.kotlin.android" version "1.9.22" apply false } include ":app" diff --git a/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list.gform.dart b/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list.gform.dart index ad752b89..50bcf0c7 100644 --- a/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list.gform.dart @@ -152,6 +152,7 @@ class _AnimatedUrlListFormBuilderState AnimatedUrlListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -194,7 +195,9 @@ class _AnimatedUrlListFormBuilderState @override void didUpdateWidget(covariant AnimatedUrlListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -230,8 +233,12 @@ final _logAnimatedUrlListForm = Logger.detached('AnimatedUrlListForm'); class AnimatedUrlListForm implements FormModel { - AnimatedUrlListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnimatedUrlListForm( + this.form, + this.path, + this._formModel, { + AnimatedUrlList? initialModel, + }) : _ownInitialModel = initialModel; static const String urlListControlName = "urlList"; @@ -244,8 +251,10 @@ class AnimatedUrlListForm final Map _disabled = {}; - @override - final Map initial; + AnimatedUrlList? _ownInitialModel; + + late Map _ownInitialRawValue = + AnimatedUrlListForm.formElements(_ownInitialModel).rawValue; String urlListControlPath() => pathBuilder(urlListControlName); @@ -505,10 +514,28 @@ class AnimatedUrlListForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AnimatedUrlList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AnimatedUrlList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnimatedUrlListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -547,55 +574,6 @@ class AnimatedUrlListForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -621,8 +599,12 @@ class AnimatedUrlListForm final _logUrlEntityForm = Logger.detached('UrlEntityForm'); class UrlEntityForm implements FormModel { - UrlEntityForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UrlEntityForm( + this.form, + this.path, + this._formModel, { + UrlEntity? initialModel, + }) : _ownInitialModel = initialModel; static const String labelControlName = "label"; @@ -637,8 +619,11 @@ class UrlEntityForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UrlEntity? _ownInitialModel; + + late Map _ownInitialRawValue = UrlEntityForm.formElements( + _ownInitialModel, + ).rawValue; String labelControlPath() => pathBuilder(labelControlName); @@ -869,10 +854,26 @@ class UrlEntityForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UrlEntity? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UrlEntity? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UrlEntityForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -911,55 +912,6 @@ class UrlEntityForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list_output.gform.dart index 4a4fa788..5ffee860 100644 --- a/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/animated_url_list/animated_url_list_output.gform.dart @@ -152,6 +152,7 @@ class _AnimatedUrlLisOFormBuilderState AnimatedUrlLisOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -194,7 +195,9 @@ class _AnimatedUrlLisOFormBuilderState @override void didUpdateWidget(covariant AnimatedUrlLisOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -230,8 +233,12 @@ final _logAnimatedUrlLisOForm = Logger.detached('AnimatedUrlLisOForm'); class AnimatedUrlLisOForm implements FormModel { - AnimatedUrlLisOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnimatedUrlLisOForm( + this.form, + this.path, + this._formModel, { + AnimatedUrlLisO? initialModel, + }) : _ownInitialModel = initialModel; static const String urlListControlName = "urlList"; @@ -244,8 +251,10 @@ class AnimatedUrlLisOForm final Map _disabled = {}; - @override - final Map initial; + AnimatedUrlLisO? _ownInitialModel; + + late Map _ownInitialRawValue = + AnimatedUrlLisOForm.formElements(_ownInitialModel).rawValue; String urlListControlPath() => pathBuilder(urlListControlName); @@ -506,10 +515,28 @@ class AnimatedUrlLisOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AnimatedUrlLisO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AnimatedUrlLisO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnimatedUrlLisOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -548,55 +575,6 @@ class AnimatedUrlLisOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -622,8 +600,12 @@ class AnimatedUrlLisOForm final _logUrlEntityOForm = Logger.detached('UrlEntityOForm'); class UrlEntityOForm implements FormModel { - UrlEntityOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UrlEntityOForm( + this.form, + this.path, + this._formModel, { + UrlEntityO? initialModel, + }) : _ownInitialModel = initialModel; static const String labelControlName = "label"; @@ -638,8 +620,11 @@ class UrlEntityOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UrlEntityO? _ownInitialModel; + + late Map _ownInitialRawValue = UrlEntityOForm.formElements( + _ownInitialModel, + ).rawValue; String labelControlPath() => pathBuilder(labelControlName); @@ -917,10 +902,28 @@ class UrlEntityOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UrlEntityO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UrlEntityO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UrlEntityOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -959,55 +962,6 @@ class UrlEntityOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 954ce156..e943fdbd 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 @@ -151,6 +151,7 @@ class _AnnotatelessFormBuilderState extends State { AnnotatelessForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _AnnotatelessFormBuilderState extends State { @override void didUpdateWidget(covariant AnnotatelessFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _AnnotatelessFormBuilderState extends State { final _logAnnotatelessForm = Logger.detached('AnnotatelessForm'); class AnnotatelessForm implements FormModel { - AnnotatelessForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnnotatelessForm( + this.form, + this.path, + this._formModel, { + Annotateless? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -244,8 +251,11 @@ class AnnotatelessForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Annotateless? _ownInitialModel; + + late Map _ownInitialRawValue = AnnotatelessForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -476,10 +486,28 @@ class AnnotatelessForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Annotateless? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Annotateless? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnnotatelessForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -518,55 +546,6 @@ class AnnotatelessForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless_output.gform.dart index d8018e4c..3b2cd820 100644 --- a/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/annotateless/annotateless_output.gform.dart @@ -151,6 +151,7 @@ class _AnnotatelessOFormBuilderState extends State { AnnotatelessOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _AnnotatelessOFormBuilderState extends State { @override void didUpdateWidget(covariant AnnotatelessOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -229,8 +232,12 @@ final _logAnnotatelessOForm = Logger.detached('AnnotatelessOForm'); class AnnotatelessOForm implements FormModel { - AnnotatelessOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AnnotatelessOForm( + this.form, + this.path, + this._formModel, { + AnnotatelessO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -245,8 +252,10 @@ class AnnotatelessOForm final Map _disabled = {}; - @override - final Map initial; + AnnotatelessO? _ownInitialModel; + + late Map _ownInitialRawValue = + AnnotatelessOForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -478,10 +487,28 @@ class AnnotatelessOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AnnotatelessO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AnnotatelessO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AnnotatelessOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -520,55 +547,6 @@ class AnnotatelessOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 230e0720..237fc185 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 @@ -151,6 +151,7 @@ class _ArrayNullableFormBuilderState extends State { ArrayNullableForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _ArrayNullableFormBuilderState extends State { @override void didUpdateWidget(covariant ArrayNullableFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _ArrayNullableFormBuilderState extends State { final _logArrayNullableForm = Logger.detached('ArrayNullableForm'); class ArrayNullableForm implements FormModel { - ArrayNullableForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ArrayNullableForm( + this.form, + this.path, + this._formModel, { + ArrayNullable? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -252,8 +259,10 @@ class ArrayNullableForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ArrayNullable? _ownInitialModel; + + late Map _ownInitialRawValue = + ArrayNullableForm.formElements(_ownInitialModel).rawValue; String someListControlPath() => pathBuilder(someListControlName); @@ -1078,10 +1087,28 @@ class ArrayNullableForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ArrayNullable? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ArrayNullable? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ArrayNullableForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1120,55 +1147,6 @@ class ArrayNullableForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable_output.gform.dart index 48f47903..5e64721a 100644 --- a/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/array_nullable/array_nullable_output.gform.dart @@ -151,6 +151,7 @@ class _ArrayNullableOFormBuilderState extends State { ArrayNullableOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _ArrayNullableOFormBuilderState extends State { @override void didUpdateWidget(covariant ArrayNullableOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -229,8 +232,12 @@ final _logArrayNullableOForm = Logger.detached('ArrayNullableOForm'); class ArrayNullableOForm implements FormModel { - ArrayNullableOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ArrayNullableOForm( + this.form, + this.path, + this._formModel, { + ArrayNullableO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -251,8 +258,10 @@ class ArrayNullableOForm final Map _disabled = {}; - @override - final Map initial; + ArrayNullableO? _ownInitialModel; + + late Map _ownInitialRawValue = + ArrayNullableOForm.formElements(_ownInitialModel).rawValue; String someListControlPath() => pathBuilder(someListControlName); @@ -994,10 +1003,28 @@ class ArrayNullableOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ArrayNullableO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ArrayNullableO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ArrayNullableOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1036,55 +1063,6 @@ class ArrayNullableOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/create/create_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/create/create_output.gform.dart index 82e1873a..379fa2e3 100644 --- a/packages/reactive_forms_generator/example/lib/docs/create/create_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/create/create_output.gform.dart @@ -146,6 +146,7 @@ class _MSICreateFormBuilderState extends State { MSICreateForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -188,7 +189,9 @@ class _MSICreateFormBuilderState extends State { @override void didUpdateWidget(covariant MSICreateFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -223,8 +226,12 @@ class _MSICreateFormBuilderState extends State { final _logMSICreateForm = Logger.detached('MSICreateForm'); class MSICreateForm implements FormModel { - MSICreateForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + MSICreateForm( + this.form, + this.path, + this._formModel, { + MSICreate? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -256,8 +263,11 @@ class MSICreateForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + MSICreate? _ownInitialModel; + + late Map _ownInitialRawValue = MSICreateForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1391,10 +1401,26 @@ class MSICreateForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + MSICreate? get initialModel { + return _ownInitialModel; + } + + void commitInitial([MSICreate? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = MSICreateForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1433,55 +1459,6 @@ class MSICreateForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1564,7 +1541,8 @@ class MSICreateForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1583,8 +1561,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -2080,10 +2061,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2122,55 +2119,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2220,8 +2168,12 @@ final _logPrimaryContactForm = Logger.detached('PrimaryContactForm'); class PrimaryContactForm implements FormModel { - PrimaryContactForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + PrimaryContactForm( + this.form, + this.path, + this._formModel, { + PrimaryContact? initialModel, + }) : _ownInitialModel = initialModel; static const String fullNameControlName = "fullName"; @@ -2238,8 +2190,10 @@ class PrimaryContactForm final Map _disabled = {}; - @override - final Map initial; + PrimaryContact? _ownInitialModel; + + late Map _ownInitialRawValue = + PrimaryContactForm.formElements(_ownInitialModel).rawValue; String fullNameControlPath() => pathBuilder(fullNameControlName); @@ -2628,10 +2582,28 @@ class PrimaryContactForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + PrimaryContact? get initialModel { + return _ownInitialModel; + } + + void commitInitial([PrimaryContact? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PrimaryContactForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2670,55 +2642,6 @@ class PrimaryContactForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2763,8 +2686,12 @@ final _logAdminContactInformationForm = Logger.detached( class AdminContactInformationForm implements FormModel { - AdminContactInformationForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AdminContactInformationForm( + this.form, + this.path, + this._formModel, { + AdminContactInformation? initialModel, + }) : _ownInitialModel = initialModel; static const String firstNameControlName = "firstName"; @@ -2781,8 +2708,10 @@ class AdminContactInformationForm final Map _disabled = {}; - @override - final Map initial; + AdminContactInformation? _ownInitialModel; + + late Map _ownInitialRawValue = + AdminContactInformationForm.formElements(_ownInitialModel).rawValue; String firstNameControlPath() => pathBuilder(firstNameControlName); @@ -3171,10 +3100,28 @@ class AdminContactInformationForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AdminContactInformation? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AdminContactInformation? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AdminContactInformationForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3213,55 +3160,6 @@ class AdminContactInformationForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 61277527..b152a47e 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 @@ -151,6 +151,7 @@ class _DeliveryListFormBuilderState extends State { DeliveryListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _DeliveryListFormBuilderState extends State { @override void didUpdateWidget(covariant DeliveryListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _DeliveryListFormBuilderState extends State { final _logDeliveryListForm = Logger.detached('DeliveryListForm'); class DeliveryListForm implements FormModel { - DeliveryListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryListForm( + this.form, + this.path, + this._formModel, { + DeliveryList? initialModel, + }) : _ownInitialModel = initialModel; static const String deliveryListControlName = "deliveryList"; @@ -244,8 +251,11 @@ class DeliveryListForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + DeliveryList? _ownInitialModel; + + late Map _ownInitialRawValue = DeliveryListForm.formElements( + _ownInitialModel, + ).rawValue; String deliveryListControlPath() => pathBuilder(deliveryListControlName); @@ -730,10 +740,28 @@ class DeliveryListForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -772,55 +800,6 @@ class DeliveryListForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -855,8 +834,12 @@ class DeliveryListForm implements FormModel { final _logDeliveryPointForm = Logger.detached('DeliveryPointForm'); class DeliveryPointForm implements FormModel { - DeliveryPointForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryPointForm( + this.form, + this.path, + this._formModel, { + DeliveryPoint? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -871,8 +854,10 @@ class DeliveryPointForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + DeliveryPoint? _ownInitialModel; + + late Map _ownInitialRawValue = + DeliveryPointForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1130,10 +1115,28 @@ class DeliveryPointForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPoint? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPoint? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryPointForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1172,55 +1175,6 @@ class DeliveryPointForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1246,7 +1200,8 @@ class DeliveryPointForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1261,8 +1216,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1539,10 +1497,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1581,55 +1555,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1662,7 +1587,8 @@ class AddressForm implements FormModel { final _logClientForm = Logger.detached('ClientForm'); class ClientForm implements FormModel { - ClientForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ClientForm(this.form, this.path, this._formModel, {Client? initialModel}) + : _ownInitialModel = initialModel; static const String clientTypeControlName = "clientType"; @@ -1679,8 +1605,11 @@ class ClientForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Client? _ownInitialModel; + + late Map _ownInitialRawValue = ClientForm.formElements( + _ownInitialModel, + ).rawValue; String clientTypeControlPath() => pathBuilder(clientTypeControlName); @@ -2043,10 +1972,26 @@ class ClientForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Client? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Client? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ClientForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2085,55 +2030,6 @@ class ClientForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2551,6 +2447,7 @@ class _StandaloneDeliveryPointFormBuilderState StandaloneDeliveryPointForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -2595,7 +2492,9 @@ class _StandaloneDeliveryPointFormBuilderState @override void didUpdateWidget(covariant StandaloneDeliveryPointFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -2633,8 +2532,12 @@ final _logStandaloneDeliveryPointForm = Logger.detached( class StandaloneDeliveryPointForm implements FormModel { - StandaloneDeliveryPointForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StandaloneDeliveryPointForm( + this.form, + this.path, + this._formModel, { + DeliveryPoint? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -2649,8 +2552,10 @@ class StandaloneDeliveryPointForm final Map _disabled = {}; - @override - final Map initial; + DeliveryPoint? _ownInitialModel; + + late Map _ownInitialRawValue = + StandaloneDeliveryPointForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -2908,10 +2813,28 @@ class StandaloneDeliveryPointForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPoint? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPoint? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StandaloneDeliveryPointForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2950,55 +2873,6 @@ class StandaloneDeliveryPointForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list_output.gform.dart index 5ef4a483..6a2f6ab0 100644 --- a/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_list_output.gform.dart @@ -151,6 +151,7 @@ class _DeliveryListOFormBuilderState extends State { DeliveryListOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _DeliveryListOFormBuilderState extends State { @override void didUpdateWidget(covariant DeliveryListOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -229,8 +232,12 @@ final _logDeliveryListOForm = Logger.detached('DeliveryListOForm'); class DeliveryListOForm implements FormModel { - DeliveryListOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryListOForm( + this.form, + this.path, + this._formModel, { + DeliveryListO? initialModel, + }) : _ownInitialModel = initialModel; static const String deliveryListControlName = "deliveryList"; @@ -245,8 +252,10 @@ class DeliveryListOForm final Map _disabled = {}; - @override - final Map initial; + DeliveryListO? _ownInitialModel; + + late Map _ownInitialRawValue = + DeliveryListOForm.formElements(_ownInitialModel).rawValue; String deliveryListControlPath() => pathBuilder(deliveryListControlName); @@ -732,10 +741,28 @@ class DeliveryListOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryListO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryListO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryListOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -774,55 +801,6 @@ class DeliveryListOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -858,8 +836,12 @@ final _logDeliveryPointOForm = Logger.detached('DeliveryPointOForm'); class DeliveryPointOForm implements FormModel { - DeliveryPointOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryPointOForm( + this.form, + this.path, + this._formModel, { + DeliveryPointO? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -874,8 +856,10 @@ class DeliveryPointOForm final Map _disabled = {}; - @override - final Map initial; + DeliveryPointO? _ownInitialModel; + + late Map _ownInitialRawValue = + DeliveryPointOForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1135,10 +1119,28 @@ class DeliveryPointOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPointO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPointO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryPointOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1177,55 +1179,6 @@ class DeliveryPointOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1251,7 +1204,8 @@ class DeliveryPointOForm final _logAddressOForm = Logger.detached('AddressOForm'); class AddressOForm implements FormModel { - AddressOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressOForm(this.form, this.path, this._formModel, {AddressO? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1266,8 +1220,11 @@ class AddressOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + AddressO? _ownInitialModel; + + late Map _ownInitialRawValue = AddressOForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1545,10 +1502,26 @@ class AddressOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AddressO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AddressO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1587,55 +1560,6 @@ class AddressOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1668,7 +1592,8 @@ class AddressOForm implements FormModel { final _logClientOForm = Logger.detached('ClientOForm'); class ClientOForm implements FormModel { - ClientOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ClientOForm(this.form, this.path, this._formModel, {ClientO? initialModel}) + : _ownInitialModel = initialModel; static const String clientTypeControlName = "clientType"; @@ -1685,8 +1610,11 @@ class ClientOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ClientO? _ownInitialModel; + + late Map _ownInitialRawValue = ClientOForm.formElements( + _ownInitialModel, + ).rawValue; String clientTypeControlPath() => pathBuilder(clientTypeControlName); @@ -2050,10 +1978,26 @@ class ClientOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ClientO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ClientO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ClientOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2092,55 +2036,6 @@ class ClientOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2609,6 +2504,7 @@ class _StandaloneDeliveryPointFormBuilderState StandaloneDeliveryPointForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -2653,7 +2549,9 @@ class _StandaloneDeliveryPointFormBuilderState @override void didUpdateWidget(covariant StandaloneDeliveryPointFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -2691,8 +2589,12 @@ final _logStandaloneDeliveryPointForm = Logger.detached( class StandaloneDeliveryPointForm implements FormModel { - StandaloneDeliveryPointForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StandaloneDeliveryPointForm( + this.form, + this.path, + this._formModel, { + DeliveryPointO? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -2707,8 +2609,10 @@ class StandaloneDeliveryPointForm final Map _disabled = {}; - @override - final Map initial; + DeliveryPointO? _ownInitialModel; + + late Map _ownInitialRawValue = + StandaloneDeliveryPointForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -2968,10 +2872,28 @@ class StandaloneDeliveryPointForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPointO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPointO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StandaloneDeliveryPointForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3010,55 +2932,6 @@ class StandaloneDeliveryPointForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_route_form.dart b/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_route_form.dart index b5c61fa5..2c4b102e 100644 --- a/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_route_form.dart +++ b/packages/reactive_forms_generator/example/lib/docs/delivery_list/delivery_route_form.dart @@ -2,6 +2,7 @@ import 'package:example/docs/delivery_list/delivery_list.dart'; import 'package:example/docs/delivery_list/labels.dart'; import 'package:example/docs/delivery_list/mocks.dart'; import 'package:example/sample_screen.dart'; +import 'package:example/widgets/dirty_badge.dart'; import 'package:flutter/material.dart' hide ProgressIndicator; import 'package:reactive_forms/reactive_forms.dart'; @@ -17,9 +18,18 @@ class DeliveryListFormWidget extends StatelessWidget { body: DeliveryListFormBuilder( model: const DeliveryList(), builder: (context, formModel, child) { - return Column( + return StreamBuilder( + stream: formModel.form.valueChanges, + builder: (context, _) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: DirtyBadge( + changed: formModel.hasChanged, + label: 'form', + ), + ), Row( children: [ Expanded( @@ -29,8 +39,17 @@ class DeliveryListFormWidget extends StatelessWidget { >( extended: formModel.deliveryListExtendedControl, itemBuilder: (context, i, formItem, _) { + final itemForm = + formModel.deliveryListDeliveryPointForm[i]; return Column( children: [ + Padding( + padding: const EdgeInsets.only(top: 4), + child: DirtyBadge( + changed: itemForm.hasChanged, + label: 'item $i', + ), + ), Row( children: [ Expanded( @@ -64,6 +83,13 @@ class DeliveryListFormWidget extends StatelessWidget { ), ], ), + Padding( + padding: const EdgeInsets.only(top: 4), + child: DirtyBadge( + changed: itemForm.addressForm.hasChanged, + label: 'address $i', + ), + ), ReactiveTextField( key: street.itemIndexKey(i), formControl: @@ -255,6 +281,7 @@ class DeliveryListFormWidget extends StatelessWidget { ], ), ], + ), ); }, ), 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 db163103..429bd717 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 @@ -151,6 +151,7 @@ class _FreezedClassFormBuilderState extends State { FreezedClassForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _FreezedClassFormBuilderState extends State { @override void didUpdateWidget(covariant FreezedClassFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _FreezedClassFormBuilderState extends State { final _logFreezedClassForm = Logger.detached('FreezedClassForm'); class FreezedClassForm implements FormModel { - FreezedClassForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + FreezedClassForm( + this.form, + this.path, + this._formModel, { + FreezedClass? initialModel, + }) : _ownInitialModel = initialModel; static const String genderControlName = "gender"; @@ -252,8 +259,11 @@ class FreezedClassForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + FreezedClass? _ownInitialModel; + + late Map _ownInitialRawValue = FreezedClassForm.formElements( + _ownInitialModel, + ).rawValue; String genderControlPath() => pathBuilder(genderControlName); @@ -924,10 +934,28 @@ class FreezedClassForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + FreezedClass? get initialModel { + return _ownInitialModel; + } + + void commitInitial([FreezedClass? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = FreezedClassForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -966,55 +994,6 @@ class FreezedClassForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class_output.gform.dart index 9cd2ed9e..cea9820c 100644 --- a/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/freezed/freezed_class_output.gform.dart @@ -151,6 +151,7 @@ class _FreezedClassOFormBuilderState extends State { FreezedClassOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _FreezedClassOFormBuilderState extends State { @override void didUpdateWidget(covariant FreezedClassOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -229,8 +232,12 @@ final _logFreezedClassOForm = Logger.detached('FreezedClassOForm'); class FreezedClassOForm implements FormModel { - FreezedClassOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + FreezedClassOForm( + this.form, + this.path, + this._formModel, { + FreezedClassO? initialModel, + }) : _ownInitialModel = initialModel; static const String genderControlName = "gender"; @@ -259,8 +266,10 @@ class FreezedClassOForm final Map _disabled = {}; - @override - final Map initial; + FreezedClassO? _ownInitialModel; + + late Map _ownInitialRawValue = + FreezedClassOForm.formElements(_ownInitialModel).rawValue; String genderControlPath() => pathBuilder(genderControlName); @@ -1218,10 +1227,28 @@ class FreezedClassOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + FreezedClassO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([FreezedClassO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = FreezedClassOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1260,55 +1287,6 @@ class FreezedClassOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 596eed40..49ffd9bd 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 @@ -128,7 +128,12 @@ class _TestFormBuilderState extends State { @override void initState() { - _formModel = TestForm(TestForm.formElements(widget.model), null, null); + _formModel = TestForm( + TestForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -170,7 +175,9 @@ class _TestFormBuilderState extends State { @override void didUpdateWidget(covariant TestFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -205,7 +212,8 @@ class _TestFormBuilderState extends State { final _logTestForm = Logger.detached('TestForm'); class TestForm implements FormModel { - TestForm(this.form, this.path, this._formModel) : initial = form.rawValue; + TestForm(this.form, this.path, this._formModel, {Test? initialModel}) + : _ownInitialModel = initialModel; static const String titleControlName = "title"; @@ -220,8 +228,11 @@ class TestForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Test? _ownInitialModel; + + late Map _ownInitialRawValue = TestForm.formElements( + _ownInitialModel, + ).rawValue; String titleControlPath() => pathBuilder(titleControlName); @@ -477,10 +488,26 @@ class TestForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Test? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Test? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TestForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -516,55 +543,6 @@ class TestForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 66a29f92..f7feea1c 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 @@ -142,6 +142,7 @@ class _TagsFormBuilderState extends State> { TagsForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -184,7 +185,9 @@ class _TagsFormBuilderState extends State> { @override void didUpdateWidget(covariant TagsFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -219,7 +222,8 @@ class _TagsFormBuilderState extends State> { final _logTagsForm = Logger.detached('TagsForm'); class TagsForm implements FormModel, Tags> { - TagsForm(this.form, this.path, this._formModel) : initial = form.rawValue; + TagsForm(this.form, this.path, this._formModel, {Tags? initialModel}) + : _ownInitialModel = initialModel; static const String tagsControlName = "tags"; @@ -232,8 +236,11 @@ class TagsForm implements FormModel, Tags> { final Map _disabled = {}; - @override - final Map initial; + Tags? _ownInitialModel; + + late Map _ownInitialRawValue = TagsForm.formElements( + _ownInitialModel, + ).rawValue; String tagsControlPath() => pathBuilder(tagsControlName); @@ -409,10 +416,26 @@ class TagsForm implements FormModel, Tags> { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Tags? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Tags? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TagsForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -451,55 +474,6 @@ class TagsForm implements FormModel, Tags> { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/generic/generic_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/generic/generic_output.gform.dart index ac3af5fc..40249aa5 100644 --- a/packages/reactive_forms_generator/example/lib/docs/generic/generic_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/generic/generic_output.gform.dart @@ -143,6 +143,7 @@ class _TagsOFormBuilderState extends State> { TagsOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -185,7 +186,9 @@ class _TagsOFormBuilderState extends State> { @override void didUpdateWidget(covariant TagsOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -220,7 +223,8 @@ class _TagsOFormBuilderState extends State> { final _logTagsOForm = Logger.detached('TagsOForm'); class TagsOForm implements FormModel, TagsOOutput> { - TagsOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + TagsOForm(this.form, this.path, this._formModel, {TagsO? initialModel}) + : _ownInitialModel = initialModel; static const String tagsControlName = "tags"; @@ -233,8 +237,11 @@ class TagsOForm implements FormModel, TagsOOutput> { final Map _disabled = {}; - @override - final Map initial; + TagsO? _ownInitialModel; + + late Map _ownInitialRawValue = TagsOForm.formElements( + _ownInitialModel, + ).rawValue; String tagsControlPath() => pathBuilder(tagsControlName); @@ -411,10 +418,26 @@ class TagsOForm implements FormModel, TagsOOutput> { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + TagsO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([TagsO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TagsOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -453,55 +476,6 @@ class TagsOForm implements FormModel, TagsOOutput> { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 8c2be228..1468b113 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 @@ -156,6 +156,7 @@ class _StatusListFormBuilderState StatusListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -198,7 +199,9 @@ class _StatusListFormBuilderState @override void didUpdateWidget(covariant StatusListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -234,8 +237,12 @@ final _logStatusListForm = Logger.detached('StatusListForm'); class StatusListForm implements FormModel, StatusList> { - StatusListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StatusListForm( + this.form, + this.path, + this._formModel, { + StatusList? initialModel, + }) : _ownInitialModel = initialModel; static const String listControlName = "list"; @@ -248,8 +255,11 @@ class StatusListForm final Map _disabled = {}; - @override - final Map initial; + StatusList? _ownInitialModel; + + late Map _ownInitialRawValue = StatusListForm.formElements( + _ownInitialModel, + ).rawValue; String listControlPath() => pathBuilder(listControlName); @@ -447,10 +457,28 @@ class StatusListForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + StatusList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([StatusList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StatusListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -489,55 +517,6 @@ class StatusListForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list_output.gform.dart index c912d9a6..6fca6a58 100644 --- a/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/generic_status_list/generic_status_list_output.gform.dart @@ -156,6 +156,7 @@ class _StatusListOFormBuilderState StatusListOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -198,7 +199,9 @@ class _StatusListOFormBuilderState @override void didUpdateWidget(covariant StatusListOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -234,8 +237,12 @@ final _logStatusListOForm = Logger.detached('StatusListOForm'); class StatusListOForm implements FormModel, StatusListOOutput> { - StatusListOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StatusListOForm( + this.form, + this.path, + this._formModel, { + StatusListO? initialModel, + }) : _ownInitialModel = initialModel; static const String listControlName = "list"; @@ -248,8 +255,11 @@ class StatusListOForm final Map _disabled = {}; - @override - final Map initial; + StatusListO? _ownInitialModel; + + late Map _ownInitialRawValue = StatusListOForm.formElements( + _ownInitialModel, + ).rawValue; String listControlPath() => pathBuilder(listControlName); @@ -448,10 +458,28 @@ class StatusListOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + StatusListO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([StatusListO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StatusListOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -490,55 +518,6 @@ class StatusListOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 fcece4d9..9ec7abde 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 @@ -136,7 +136,12 @@ class _GroupFormBuilderState extends State { @override void initState() { - _formModel = GroupForm(GroupForm.formElements(widget.model), null, null); + _formModel = GroupForm( + GroupForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -178,7 +183,9 @@ class _GroupFormBuilderState extends State { @override void didUpdateWidget(covariant GroupFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -213,7 +220,8 @@ class _GroupFormBuilderState extends State { final _logGroupForm = Logger.detached('GroupForm'); class GroupForm implements FormModel { - GroupForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupForm(this.form, this.path, this._formModel, {Group? initialModel}) + : _ownInitialModel = initialModel; static const String personalControlName = "personal"; @@ -232,8 +240,11 @@ class GroupForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Group? _ownInitialModel; + + late Map _ownInitialRawValue = GroupForm.formElements( + _ownInitialModel, + ).rawValue; String personalControlPath() => pathBuilder(personalControlName); @@ -736,10 +747,26 @@ class GroupForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Group? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Group? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -775,55 +802,6 @@ class GroupForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -844,7 +822,8 @@ class GroupForm implements FormModel { final _logPersonalForm = Logger.detached('PersonalForm'); class PersonalForm implements FormModel { - PersonalForm(this.form, this.path, this._formModel) : initial = form.rawValue; + PersonalForm(this.form, this.path, this._formModel, {Personal? initialModel}) + : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -859,8 +838,11 @@ class PersonalForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Personal? _ownInitialModel; + + late Map _ownInitialRawValue = PersonalForm.formElements( + _ownInitialModel, + ).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1137,10 +1119,26 @@ class PersonalForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Personal? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Personal? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PersonalForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1179,55 +1177,6 @@ class PersonalForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1260,7 +1209,8 @@ class PersonalForm implements FormModel { final _logPhoneForm = Logger.detached('PhoneForm'); class PhoneForm implements FormModel { - PhoneForm(this.form, this.path, this._formModel) : initial = form.rawValue; + PhoneForm(this.form, this.path, this._formModel, {Phone? initialModel}) + : _ownInitialModel = initialModel; static const String phoneNumberControlName = "phoneNumber"; @@ -1275,8 +1225,11 @@ class PhoneForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Phone? _ownInitialModel; + + late Map _ownInitialRawValue = PhoneForm.formElements( + _ownInitialModel, + ).rawValue; String phoneNumberControlPath() => pathBuilder(phoneNumberControlName); @@ -1560,10 +1513,26 @@ class PhoneForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Phone? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Phone? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PhoneForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1599,55 +1568,6 @@ class PhoneForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1680,7 +1600,8 @@ class PhoneForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1697,8 +1618,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -2080,10 +2004,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2122,55 +2062,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/group/group_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/group/group_output.gform.dart index ddbcc197..60b43d3d 100644 --- a/packages/reactive_forms_generator/example/lib/docs/group/group_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/group/group_output.gform.dart @@ -139,7 +139,12 @@ class _GroupOFormBuilderState extends State { @override void initState() { - _formModel = GroupOForm(GroupOForm.formElements(widget.model), null, null); + _formModel = GroupOForm( + GroupOForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -181,7 +186,9 @@ class _GroupOFormBuilderState extends State { @override void didUpdateWidget(covariant GroupOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -216,7 +223,8 @@ class _GroupOFormBuilderState extends State { final _logGroupOForm = Logger.detached('GroupOForm'); class GroupOForm implements FormModel { - GroupOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupOForm(this.form, this.path, this._formModel, {GroupO? initialModel}) + : _ownInitialModel = initialModel; static const String personalControlName = "personal"; @@ -235,8 +243,11 @@ class GroupOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + GroupO? _ownInitialModel; + + late Map _ownInitialRawValue = GroupOForm.formElements( + _ownInitialModel, + ).rawValue; String personalControlPath() => pathBuilder(personalControlName); @@ -743,10 +754,26 @@ class GroupOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + GroupO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([GroupO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -785,55 +812,6 @@ class GroupOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -854,8 +832,12 @@ class GroupOForm implements FormModel { final _logPersonalOForm = Logger.detached('PersonalOForm'); class PersonalOForm implements FormModel { - PersonalOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + PersonalOForm( + this.form, + this.path, + this._formModel, { + PersonalO? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -870,8 +852,11 @@ class PersonalOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + PersonalO? _ownInitialModel; + + late Map _ownInitialRawValue = PersonalOForm.formElements( + _ownInitialModel, + ).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1149,10 +1134,26 @@ class PersonalOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + PersonalO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([PersonalO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PersonalOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1191,55 +1192,6 @@ class PersonalOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1272,7 +1224,8 @@ class PersonalOForm implements FormModel { final _logPhoneOForm = Logger.detached('PhoneOForm'); class PhoneOForm implements FormModel { - PhoneOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + PhoneOForm(this.form, this.path, this._formModel, {PhoneO? initialModel}) + : _ownInitialModel = initialModel; static const String phoneNumberControlName = "phoneNumber"; @@ -1287,8 +1240,11 @@ class PhoneOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + PhoneO? _ownInitialModel; + + late Map _ownInitialRawValue = PhoneOForm.formElements( + _ownInitialModel, + ).rawValue; String phoneNumberControlPath() => pathBuilder(phoneNumberControlName); @@ -1576,10 +1532,26 @@ class PhoneOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + PhoneO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([PhoneO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PhoneOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1618,55 +1590,6 @@ class PhoneOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1699,7 +1622,8 @@ class PhoneOForm implements FormModel { final _logAddressOForm = Logger.detached('AddressOForm'); class AddressOForm implements FormModel { - AddressOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressOForm(this.form, this.path, this._formModel, {AddressO? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1716,8 +1640,11 @@ class AddressOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + AddressO? _ownInitialModel; + + late Map _ownInitialRawValue = AddressOForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -2104,10 +2031,26 @@ class AddressOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AddressO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AddressO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2146,55 +2089,6 @@ class AddressOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/issue_203/issue_203.gform.dart b/packages/reactive_forms_generator/example/lib/docs/issue_203/issue_203.gform.dart index a3e4a3c5..1be6ab9c 100644 --- a/packages/reactive_forms_generator/example/lib/docs/issue_203/issue_203.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/issue_203/issue_203.gform.dart @@ -151,6 +151,7 @@ class _LoginFormModelFormBuilderState extends State { LoginFormModelForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _LoginFormModelFormBuilderState extends State { @override void didUpdateWidget(covariant LoginFormModelFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _LoginFormModelFormBuilderState extends State { final _logLoginFormModelForm = Logger.detached('LoginFormModelForm'); class LoginFormModelForm implements FormModel { - LoginFormModelForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginFormModelForm( + this.form, + this.path, + this._formModel, { + LoginFormModel? initialModel, + }) : _ownInitialModel = initialModel; static const String domainControlName = "domain"; @@ -248,8 +255,10 @@ class LoginFormModelForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + LoginFormModel? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginFormModelForm.formElements(_ownInitialModel).rawValue; String domainControlPath() => pathBuilder(domainControlName); @@ -646,10 +655,28 @@ class LoginFormModelForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginFormModel? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginFormModel? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginFormModelForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -688,55 +715,6 @@ class LoginFormModelForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 3f7666cd..ecbf3cc2 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 @@ -136,7 +136,12 @@ class _LoginFormBuilderState extends State { @override void initState() { - _formModel = LoginForm(LoginForm.formElements(widget.model), null, null); + _formModel = LoginForm( + LoginForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -178,7 +183,9 @@ class _LoginFormBuilderState extends State { @override void didUpdateWidget(covariant LoginFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -213,7 +220,8 @@ class _LoginFormBuilderState extends State { final _logLoginForm = Logger.detached('LoginForm'); class LoginForm implements FormModel { - LoginForm(this.form, this.path, this._formModel) : initial = form.rawValue; + LoginForm(this.form, this.path, this._formModel, {Login? initialModel}) + : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -228,8 +236,11 @@ class LoginForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Login? _ownInitialModel; + + late Map _ownInitialRawValue = LoginForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -483,10 +494,26 @@ class LoginForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Login? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Login? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -522,55 +549,6 @@ class LoginForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 e18f5ec5..c913ff93 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 @@ -139,7 +139,12 @@ class _LoginOFormBuilderState extends State { @override void initState() { - _formModel = LoginOForm(LoginOForm.formElements(widget.model), null, null); + _formModel = LoginOForm( + LoginOForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -181,7 +186,9 @@ class _LoginOFormBuilderState extends State { @override void didUpdateWidget(covariant LoginOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -216,7 +223,8 @@ class _LoginOFormBuilderState extends State { final _logLoginOForm = Logger.detached('LoginOForm'); class LoginOForm implements FormModel { - LoginOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + LoginOForm(this.form, this.path, this._formModel, {LoginO? initialModel}) + : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -231,8 +239,11 @@ class LoginOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + LoginO? _ownInitialModel; + + late Map _ownInitialRawValue = LoginOForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -511,10 +522,26 @@ class LoginOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -553,55 +580,6 @@ class LoginOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 97154175..a89c5f08 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 @@ -151,6 +151,7 @@ class _LoginExtendedFormBuilderState extends State { LoginExtendedForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _LoginExtendedFormBuilderState extends State { @override void didUpdateWidget(covariant LoginExtendedFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _LoginExtendedFormBuilderState extends State { final _logLoginExtendedForm = Logger.detached('LoginExtendedForm'); class LoginExtendedForm implements FormModel { - LoginExtendedForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedForm( + this.form, + this.path, + this._formModel, { + LoginExtended? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -258,8 +265,10 @@ class LoginExtendedForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + LoginExtended? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1081,10 +1090,28 @@ class LoginExtendedForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtended? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtended? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1123,55 +1150,6 @@ class LoginExtendedForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended_output.gform.dart index d9e086e7..64b9456e 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login_extended/login_extended_output.gform.dart @@ -151,6 +151,7 @@ class _LoginExtendedOFormBuilderState extends State { LoginExtendedOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _LoginExtendedOFormBuilderState extends State { @override void didUpdateWidget(covariant LoginExtendedOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -229,8 +232,12 @@ final _logLoginExtendedOForm = Logger.detached('LoginExtendedOForm'); class LoginExtendedOForm implements FormModel { - LoginExtendedOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedOForm( + this.form, + this.path, + this._formModel, { + LoginExtendedO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -261,8 +268,10 @@ class LoginExtendedOForm final Map _disabled = {}; - @override - final Map initial; + LoginExtendedO? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedOForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1188,10 +1197,28 @@ class LoginExtendedOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtendedO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtendedO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1230,55 +1257,6 @@ class LoginExtendedOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 65bfd3d1..ae6ecebd 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 @@ -159,6 +159,7 @@ class _LoginExtendedNullableFormBuilderState LoginExtendedNullableForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -203,7 +204,9 @@ class _LoginExtendedNullableFormBuilderState @override void didUpdateWidget(covariant LoginExtendedNullableFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -241,8 +244,12 @@ final _logLoginExtendedNullableForm = Logger.detached( class LoginExtendedNullableForm implements FormModel { - LoginExtendedNullableForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedNullableForm( + this.form, + this.path, + this._formModel, { + LoginExtendedNullable? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -267,8 +274,10 @@ class LoginExtendedNullableForm final Map _disabled = {}; - @override - final Map initial; + LoginExtendedNullable? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedNullableForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1069,10 +1078,28 @@ class LoginExtendedNullableForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtendedNullable? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtendedNullable? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedNullableForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1111,55 +1138,6 @@ class LoginExtendedNullableForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable_output.gform.dart index 841a1e72..03e3dbf8 100644 --- a/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/login_extended_nullable/login_extended_nullable_output.gform.dart @@ -159,6 +159,7 @@ class _LoginExtendedNullableOFormBuilderState LoginExtendedNullableOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -203,7 +204,9 @@ class _LoginExtendedNullableOFormBuilderState @override void didUpdateWidget(covariant LoginExtendedNullableOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -241,8 +244,12 @@ final _logLoginExtendedNullableOForm = Logger.detached( class LoginExtendedNullableOForm implements FormModel { - LoginExtendedNullableOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedNullableOForm( + this.form, + this.path, + this._formModel, { + LoginExtendedNullableO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -267,8 +274,10 @@ class LoginExtendedNullableOForm final Map _disabled = {}; - @override - final Map initial; + LoginExtendedNullableO? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedNullableOForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1070,10 +1079,28 @@ class LoginExtendedNullableOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtendedNullableO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtendedNullableO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedNullableOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1112,55 +1139,6 @@ class LoginExtendedNullableOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 dbc01d47..57dce11b 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 @@ -149,6 +149,7 @@ class _MailingListFormBuilderState extends State { MailingListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -191,7 +192,9 @@ class _MailingListFormBuilderState extends State { @override void didUpdateWidget(covariant MailingListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -226,8 +229,12 @@ class _MailingListFormBuilderState extends State { final _logMailingListForm = Logger.detached('MailingListForm'); class MailingListForm implements FormModel { - MailingListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + MailingListForm( + this.form, + this.path, + this._formModel, { + MailingList? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -240,8 +247,11 @@ class MailingListForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + MailingList? _ownInitialModel; + + late Map _ownInitialRawValue = MailingListForm.formElements( + _ownInitialModel, + ).rawValue; String emailListControlPath() => pathBuilder(emailListControlName); @@ -441,10 +451,28 @@ class MailingListForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + MailingList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([MailingList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = MailingListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -483,55 +511,6 @@ class MailingListForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list_output.gform.dart index e52daab5..3dd1ce4c 100644 --- a/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/mailing_list/mailing_list_output.gform.dart @@ -151,6 +151,7 @@ class _MailingListOFormBuilderState extends State { MailingListOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _MailingListOFormBuilderState extends State { @override void didUpdateWidget(covariant MailingListOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _MailingListOFormBuilderState extends State { final _logMailingListOForm = Logger.detached('MailingListOForm'); class MailingListOForm implements FormModel { - MailingListOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + MailingListOForm( + this.form, + this.path, + this._formModel, { + MailingListO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -242,8 +249,11 @@ class MailingListOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + MailingListO? _ownInitialModel; + + late Map _ownInitialRawValue = MailingListOForm.formElements( + _ownInitialModel, + ).rawValue; String emailListControlPath() => pathBuilder(emailListControlName); @@ -444,10 +454,28 @@ class MailingListOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + MailingListO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([MailingListO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = MailingListOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -486,55 +514,6 @@ class MailingListOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 bd8bcab6..c57eeb4c 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 @@ -151,6 +151,7 @@ class _ModelExtendsFormBuilderState extends State { ModelExtendsForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _ModelExtendsFormBuilderState extends State { @override void didUpdateWidget(covariant ModelExtendsFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _ModelExtendsFormBuilderState extends State { final _logModelExtendsForm = Logger.detached('ModelExtendsForm'); class ModelExtendsForm implements FormModel { - ModelExtendsForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ModelExtendsForm( + this.form, + this.path, + this._formModel, { + ModelExtends? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -244,8 +251,11 @@ class ModelExtendsForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ModelExtends? _ownInitialModel; + + late Map _ownInitialRawValue = ModelExtendsForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -476,10 +486,28 @@ class ModelExtendsForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ModelExtends? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ModelExtends? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ModelExtendsForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -518,55 +546,6 @@ class ModelExtendsForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 10c337d4..dd610532 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 @@ -152,6 +152,7 @@ class _ModelImplementsFormBuilderState ModelImplementsForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -194,7 +195,9 @@ class _ModelImplementsFormBuilderState @override void didUpdateWidget(covariant ModelImplementsFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -230,8 +233,12 @@ final _logModelImplementsForm = Logger.detached('ModelImplementsForm'); class ModelImplementsForm implements FormModel { - ModelImplementsForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ModelImplementsForm( + this.form, + this.path, + this._formModel, { + ModelImplements? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -246,8 +253,10 @@ class ModelImplementsForm final Map _disabled = {}; - @override - final Map initial; + ModelImplements? _ownInitialModel; + + late Map _ownInitialRawValue = + ModelImplementsForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -478,10 +487,28 @@ class ModelImplementsForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ModelImplements? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ModelImplements? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ModelImplementsForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -520,55 +547,6 @@ class ModelImplementsForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 4ab2177c..66901d19 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 @@ -146,6 +146,7 @@ class _SubGroupFormBuilderState extends State { SubGroupForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -188,7 +189,9 @@ class _SubGroupFormBuilderState extends State { @override void didUpdateWidget(covariant SubGroupFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -223,7 +226,8 @@ class _SubGroupFormBuilderState extends State { final _logSubGroupForm = Logger.detached('SubGroupForm'); class SubGroupForm implements FormModel { - SubGroupForm(this.form, this.path, this._formModel) : initial = form.rawValue; + SubGroupForm(this.form, this.path, this._formModel, {SubGroup? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -236,8 +240,11 @@ class SubGroupForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + SubGroup? _ownInitialModel; + + late Map _ownInitialRawValue = SubGroupForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -387,10 +394,26 @@ class SubGroupForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + SubGroup? get initialModel { + return _ownInitialModel; + } + + void commitInitial([SubGroup? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SubGroupForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -429,55 +452,6 @@ class SubGroupForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -847,7 +821,12 @@ class _GroupFormBuilderState extends State { @override void initState() { - _formModel = GroupForm(GroupForm.formElements(widget.model), null, null); + _formModel = GroupForm( + GroupForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -889,7 +868,9 @@ class _GroupFormBuilderState extends State { @override void didUpdateWidget(covariant GroupFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -924,7 +905,8 @@ class _GroupFormBuilderState extends State { final _logGroupForm = Logger.detached('GroupForm'); class GroupForm implements FormModel { - GroupForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupForm(this.form, this.path, this._formModel, {Group? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -939,8 +921,11 @@ class GroupForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Group? _ownInitialModel; + + late Map _ownInitialRawValue = GroupForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1281,10 +1266,26 @@ class GroupForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Group? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Group? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1320,55 +1321,6 @@ class GroupForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1749,7 +1701,12 @@ class _NestedFormBuilderState extends State { @override void initState() { - _formModel = NestedForm(NestedForm.formElements(widget.model), null, null); + _formModel = NestedForm( + NestedForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -1791,7 +1748,9 @@ class _NestedFormBuilderState extends State { @override void didUpdateWidget(covariant NestedFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -1826,7 +1785,8 @@ class _NestedFormBuilderState extends State { final _logNestedForm = Logger.detached('NestedForm'); class NestedForm implements FormModel { - NestedForm(this.form, this.path, this._formModel) : initial = form.rawValue; + NestedForm(this.form, this.path, this._formModel, {Nested? initialModel}) + : _ownInitialModel = initialModel; static const String groupListControlName = "groupList"; @@ -1839,8 +1799,11 @@ class NestedForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Nested? _ownInitialModel; + + late Map _ownInitialRawValue = NestedForm.formElements( + _ownInitialModel, + ).rawValue; String groupListControlPath() => pathBuilder(groupListControlName); @@ -2100,10 +2063,26 @@ class NestedForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Nested? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Nested? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = NestedForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2142,55 +2121,6 @@ class NestedForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/nested/nested_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/nested/nested_output.gform.dart index 7f8d8a71..5f32ac82 100644 --- a/packages/reactive_forms_generator/example/lib/docs/nested/nested_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/nested/nested_output.gform.dart @@ -146,6 +146,7 @@ class _SubGroupOFormBuilderState extends State { SubGroupOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -188,7 +189,9 @@ class _SubGroupOFormBuilderState extends State { @override void didUpdateWidget(covariant SubGroupOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -223,8 +226,12 @@ class _SubGroupOFormBuilderState extends State { final _logSubGroupOForm = Logger.detached('SubGroupOForm'); class SubGroupOForm implements FormModel { - SubGroupOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SubGroupOForm( + this.form, + this.path, + this._formModel, { + SubGroupO? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -237,8 +244,11 @@ class SubGroupOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + SubGroupO? _ownInitialModel; + + late Map _ownInitialRawValue = SubGroupOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -389,10 +399,26 @@ class SubGroupOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + SubGroupO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([SubGroupO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SubGroupOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -431,55 +457,6 @@ class SubGroupOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -885,7 +862,12 @@ class _GroupOFormBuilderState extends State { @override void initState() { - _formModel = GroupOForm(GroupOForm.formElements(widget.model), null, null); + _formModel = GroupOForm( + GroupOForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -927,7 +909,9 @@ class _GroupOFormBuilderState extends State { @override void didUpdateWidget(covariant GroupOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -962,7 +946,8 @@ class _GroupOFormBuilderState extends State { final _logGroupOForm = Logger.detached('GroupOForm'); class GroupOForm implements FormModel { - GroupOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupOForm(this.form, this.path, this._formModel, {GroupO? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -977,8 +962,11 @@ class GroupOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + GroupO? _ownInitialModel; + + late Map _ownInitialRawValue = GroupOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1320,10 +1308,26 @@ class GroupOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + GroupO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([GroupO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1362,55 +1366,6 @@ class GroupOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1798,6 +1753,7 @@ class _NestedOFormBuilderState extends State { NestedOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -1840,7 +1796,9 @@ class _NestedOFormBuilderState extends State { @override void didUpdateWidget(covariant NestedOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -1875,7 +1833,8 @@ class _NestedOFormBuilderState extends State { final _logNestedOForm = Logger.detached('NestedOForm'); class NestedOForm implements FormModel { - NestedOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + NestedOForm(this.form, this.path, this._formModel, {NestedO? initialModel}) + : _ownInitialModel = initialModel; static const String groupListControlName = "groupList"; @@ -1888,8 +1847,11 @@ class NestedOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + NestedO? _ownInitialModel; + + late Map _ownInitialRawValue = NestedOForm.formElements( + _ownInitialModel, + ).rawValue; String groupListControlPath() => pathBuilder(groupListControlName); @@ -2150,10 +2112,26 @@ class NestedOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + NestedO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([NestedO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = NestedOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2192,55 +2170,6 @@ class NestedOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics.gform.dart b/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics.gform.dart index 725801fe..802c804a 100644 --- a/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics.gform.dart @@ -161,6 +161,7 @@ class _ProductDetailsFormBuilderState

ProductDetailsForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -203,7 +204,9 @@ class _ProductDetailsFormBuilderState

@override void didUpdateWidget(covariant ProductDetailsFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -239,8 +242,12 @@ final _logProductDetailsForm = Logger.detached('ProductDetailsForm'); class ProductDetailsForm

implements FormModel, ProductDetails> { - ProductDetailsForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ProductDetailsForm( + this.form, + this.path, + this._formModel, { + ProductDetails? initialModel, + }) : _ownInitialModel = initialModel; static const String descriptionControlName = "description"; @@ -255,8 +262,10 @@ class ProductDetailsForm

final Map _disabled = {}; - @override - final Map initial; + ProductDetails? _ownInitialModel; + + late Map _ownInitialRawValue = + ProductDetailsForm.formElements(_ownInitialModel).rawValue; String descriptionControlPath() => pathBuilder(descriptionControlName); @@ -537,10 +546,28 @@ class ProductDetailsForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ProductDetails? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ProductDetails? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProductDetailsForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -579,55 +606,6 @@ class ProductDetailsForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -656,7 +634,8 @@ final _logIdForm = Logger.detached('IdForm'); class IdForm

implements FormModel, Id> { - IdForm(this.form, this.path, this._formModel) : initial = form.rawValue; + IdForm(this.form, this.path, this._formModel, {Id? initialModel}) + : _ownInitialModel = initialModel; static const String companyNameControlName = "companyName"; @@ -671,8 +650,11 @@ class IdForm

final Map _disabled = {}; - @override - final Map initial; + Id? _ownInitialModel; + + late Map _ownInitialRawValue = IdForm.formElements( + _ownInitialModel, + ).rawValue; String companyNameControlPath() => pathBuilder(companyNameControlName); @@ -951,10 +933,26 @@ class IdForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Id? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Id? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IdForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -993,55 +991,6 @@ class IdForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1459,6 +1408,7 @@ class _IdFormBuilderState

IdForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -1501,7 +1451,9 @@ class _IdFormBuilderState

@override void didUpdateWidget(covariant IdFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); diff --git a/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics_output.gform.dart index baccc8ca..56bc3010 100644 --- a/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/nested_generics/nested_generics_output.gform.dart @@ -164,6 +164,7 @@ class _ProductDetailsOFormBuilderState

ProductDetailsOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -206,7 +207,9 @@ class _ProductDetailsOFormBuilderState

@override void didUpdateWidget(covariant ProductDetailsOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -242,8 +245,12 @@ final _logProductDetailsOForm = Logger.detached('ProductDetailsOForm'); class ProductDetailsOForm

implements FormModel, ProductDetailsOOutput> { - ProductDetailsOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ProductDetailsOForm( + this.form, + this.path, + this._formModel, { + ProductDetailsO? initialModel, + }) : _ownInitialModel = initialModel; static const String descriptionControlName = "description"; @@ -258,8 +265,10 @@ class ProductDetailsOForm

final Map _disabled = {}; - @override - final Map initial; + ProductDetailsO? _ownInitialModel; + + late Map _ownInitialRawValue = + ProductDetailsOForm.formElements(_ownInitialModel).rawValue; String descriptionControlPath() => pathBuilder(descriptionControlName); @@ -544,10 +553,28 @@ class ProductDetailsOForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ProductDetailsO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ProductDetailsO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProductDetailsOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -586,55 +613,6 @@ class ProductDetailsOForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -663,7 +641,8 @@ final _logIdOForm = Logger.detached('IdOForm'); class IdOForm

implements FormModel, IdOOutput> { - IdOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + IdOForm(this.form, this.path, this._formModel, {IdO? initialModel}) + : _ownInitialModel = initialModel; static const String companyNameControlName = "companyName"; @@ -678,8 +657,11 @@ class IdOForm

final Map _disabled = {}; - @override - final Map initial; + IdO? _ownInitialModel; + + late Map _ownInitialRawValue = IdOForm.formElements( + _ownInitialModel, + ).rawValue; String companyNameControlPath() => pathBuilder(companyNameControlName); @@ -959,10 +941,26 @@ class IdOForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + IdO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([IdO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IdOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1001,55 +999,6 @@ class IdOForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1490,6 +1439,7 @@ class _IdOFormBuilderState

IdOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -1532,7 +1482,9 @@ class _IdOFormBuilderState

@override void didUpdateWidget(covariant IdOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); 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 54332a33..238e0c15 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 @@ -145,6 +145,7 @@ class _ProfileFormBuilderState extends State { ProfileForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -187,7 +188,9 @@ class _ProfileFormBuilderState extends State { @override void didUpdateWidget(covariant ProfileFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -222,7 +225,8 @@ class _ProfileFormBuilderState extends State { final _logProfileForm = Logger.detached('ProfileForm'); class ProfileForm implements FormModel { - ProfileForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ProfileForm(this.form, this.path, this._formModel, {Profile? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -253,8 +257,11 @@ class ProfileForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Profile? _ownInitialModel; + + late Map _ownInitialRawValue = ProfileForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1154,10 +1161,26 @@ class ProfileForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Profile? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Profile? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProfileForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1196,55 +1219,6 @@ class ProfileForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1325,8 +1299,12 @@ final _logIncidenceFilterForm = Logger.detached('IncidenceFilterForm'); class IncidenceFilterForm implements FormModel { - IncidenceFilterForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + IncidenceFilterForm( + this.form, + this.path, + this._formModel, { + IncidenceFilter? initialModel, + }) : _ownInitialModel = initialModel; static const String isMobilityEnabledControlName = "isMobilityEnabled"; @@ -1349,8 +1327,10 @@ class IncidenceFilterForm final Map _disabled = {}; - @override - final Map initial; + IncidenceFilter? _ownInitialModel; + + late Map _ownInitialRawValue = + IncidenceFilterForm.formElements(_ownInitialModel).rawValue; String isMobilityEnabledControlPath() => pathBuilder(isMobilityEnabledControlName); @@ -1924,10 +1904,28 @@ class IncidenceFilterForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + IncidenceFilter? get initialModel { + return _ownInitialModel; + } + + void commitInitial([IncidenceFilter? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IncidenceFilterForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1966,55 +1964,6 @@ class IncidenceFilterForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2080,8 +2029,12 @@ final _logThresholdSettingForm = Logger.detached('ThresholdSettingForm'); class ThresholdSettingForm implements FormModel { - ThresholdSettingForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ThresholdSettingForm( + this.form, + this.path, + this._formModel, { + ThresholdSetting? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2096,8 +2049,10 @@ class ThresholdSettingForm final Map _disabled = {}; - @override - final Map initial; + ThresholdSetting? _ownInitialModel; + + late Map _ownInitialRawValue = + ThresholdSettingForm.formElements(_ownInitialModel).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2331,10 +2286,28 @@ class ThresholdSettingForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ThresholdSetting? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ThresholdSetting? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ThresholdSettingForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2373,55 +2346,6 @@ class ThresholdSettingForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2455,8 +2379,12 @@ class ThresholdSettingForm final _logTimerSettingForm = Logger.detached('TimerSettingForm'); class TimerSettingForm implements FormModel { - TimerSettingForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + TimerSettingForm( + this.form, + this.path, + this._formModel, { + TimerSetting? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2471,8 +2399,11 @@ class TimerSettingForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + TimerSetting? _ownInitialModel; + + late Map _ownInitialRawValue = TimerSettingForm.formElements( + _ownInitialModel, + ).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2703,10 +2634,28 @@ class TimerSettingForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + TimerSetting? get initialModel { + return _ownInitialModel; + } + + void commitInitial([TimerSetting? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TimerSettingForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2745,55 +2694,6 @@ class TimerSettingForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/profile/profile_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/profile/profile_output.gform.dart index f4f902e5..e556ccb5 100644 --- a/packages/reactive_forms_generator/example/lib/docs/profile/profile_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/profile/profile_output.gform.dart @@ -146,6 +146,7 @@ class _ProfileOFormBuilderState extends State { ProfileOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -188,7 +189,9 @@ class _ProfileOFormBuilderState extends State { @override void didUpdateWidget(covariant ProfileOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -223,7 +226,8 @@ class _ProfileOFormBuilderState extends State { final _logProfileOForm = Logger.detached('ProfileOForm'); class ProfileOForm implements FormModel { - ProfileOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ProfileOForm(this.form, this.path, this._formModel, {ProfileO? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -254,8 +258,11 @@ class ProfileOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ProfileO? _ownInitialModel; + + late Map _ownInitialRawValue = ProfileOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1156,10 +1163,26 @@ class ProfileOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ProfileO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ProfileO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProfileOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1198,55 +1221,6 @@ class ProfileOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1327,8 +1301,12 @@ final _logIncidenceFilterOForm = Logger.detached('IncidenceFilterOForm'); class IncidenceFilterOForm implements FormModel { - IncidenceFilterOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + IncidenceFilterOForm( + this.form, + this.path, + this._formModel, { + IncidenceFilterO? initialModel, + }) : _ownInitialModel = initialModel; static const String isMobilityEnabledControlName = "isMobilityEnabled"; @@ -1351,8 +1329,10 @@ class IncidenceFilterOForm final Map _disabled = {}; - @override - final Map initial; + IncidenceFilterO? _ownInitialModel; + + late Map _ownInitialRawValue = + IncidenceFilterOForm.formElements(_ownInitialModel).rawValue; String isMobilityEnabledControlPath() => pathBuilder(isMobilityEnabledControlName); @@ -1927,10 +1907,28 @@ class IncidenceFilterOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + IncidenceFilterO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([IncidenceFilterO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IncidenceFilterOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1969,55 +1967,6 @@ class IncidenceFilterOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2084,8 +2033,12 @@ final _logThresholdSettingOForm = Logger.detached('ThresholdSettingOForm'); class ThresholdSettingOForm implements FormModel { - ThresholdSettingOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ThresholdSettingOForm( + this.form, + this.path, + this._formModel, { + ThresholdSettingO? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2100,8 +2053,10 @@ class ThresholdSettingOForm final Map _disabled = {}; - @override - final Map initial; + ThresholdSettingO? _ownInitialModel; + + late Map _ownInitialRawValue = + ThresholdSettingOForm.formElements(_ownInitialModel).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2339,10 +2294,28 @@ class ThresholdSettingOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ThresholdSettingO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ThresholdSettingO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ThresholdSettingOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2381,55 +2354,6 @@ class ThresholdSettingOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2464,8 +2388,12 @@ final _logTimerSettingOForm = Logger.detached('TimerSettingOForm'); class TimerSettingOForm implements FormModel { - TimerSettingOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + TimerSettingOForm( + this.form, + this.path, + this._formModel, { + TimerSettingO? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2480,8 +2408,10 @@ class TimerSettingOForm final Map _disabled = {}; - @override - final Map initial; + TimerSettingO? _ownInitialModel; + + late Map _ownInitialRawValue = + TimerSettingOForm.formElements(_ownInitialModel).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2713,10 +2643,28 @@ class TimerSettingOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + TimerSettingO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([TimerSettingO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TimerSettingOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2755,55 +2703,6 @@ class TimerSettingOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/recursive/recursive.gform.dart b/packages/reactive_forms_generator/example/lib/docs/recursive/recursive.gform.dart index 13d0172d..f2ed795c 100644 --- a/packages/reactive_forms_generator/example/lib/docs/recursive/recursive.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/recursive/recursive.gform.dart @@ -149,6 +149,7 @@ class _SecuredAreaFormBuilderState extends State { SecuredAreaForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -191,7 +192,9 @@ class _SecuredAreaFormBuilderState extends State { @override void didUpdateWidget(covariant SecuredAreaFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -226,8 +229,12 @@ class _SecuredAreaFormBuilderState extends State { final _logSecuredAreaForm = Logger.detached('SecuredAreaForm'); class SecuredAreaForm implements FormModel { - SecuredAreaForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SecuredAreaForm( + this.form, + this.path, + this._formModel, { + SecuredArea? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -246,8 +253,11 @@ class SecuredAreaForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + SecuredArea? _ownInitialModel; + + late Map _ownInitialRawValue = SecuredAreaForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -838,10 +848,28 @@ class SecuredAreaForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + SecuredArea? get initialModel { + return _ownInitialModel; + } + + void commitInitial([SecuredArea? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SecuredAreaForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -880,55 +908,6 @@ class SecuredAreaForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -968,8 +947,12 @@ class SecuredAreaForm implements FormModel { final _logParcelSystemForm = Logger.detached('ParcelSystemForm'); class ParcelSystemForm implements FormModel { - ParcelSystemForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ParcelSystemForm( + this.form, + this.path, + this._formModel, { + ParcelSystem? initialModel, + }) : _ownInitialModel = initialModel; static const String hasParcelSystemControlName = "hasParcelSystem"; @@ -984,8 +967,11 @@ class ParcelSystemForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ParcelSystem? _ownInitialModel; + + late Map _ownInitialRawValue = ParcelSystemForm.formElements( + _ownInitialModel, + ).rawValue; String hasParcelSystemControlPath() => pathBuilder(hasParcelSystemControlName); @@ -1226,10 +1212,28 @@ class ParcelSystemForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ParcelSystem? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ParcelSystem? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ParcelSystemForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1268,55 +1272,6 @@ class ParcelSystemForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1343,8 +1298,12 @@ final _logParcelSystemDataForm = Logger.detached('ParcelSystemDataForm'); class ParcelSystemDataForm implements FormModel { - ParcelSystemDataForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ParcelSystemDataForm( + this.form, + this.path, + this._formModel, { + ParcelSystemData? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -1357,8 +1316,10 @@ class ParcelSystemDataForm final Map _disabled = {}; - @override - final Map initial; + ParcelSystemData? _ownInitialModel; + + late Map _ownInitialRawValue = + ParcelSystemDataForm.formElements(_ownInitialModel).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1531,10 +1492,28 @@ class ParcelSystemDataForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ParcelSystemData? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ParcelSystemData? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ParcelSystemDataForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1573,55 +1552,6 @@ class ParcelSystemDataForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 92bcdc84..3a224876 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 @@ -151,6 +151,7 @@ class _SomeWiredNameFormBuilderState extends State { SomeWiredNameForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _SomeWiredNameFormBuilderState extends State { @override void didUpdateWidget(covariant SomeWiredNameFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _SomeWiredNameFormBuilderState extends State { final _logSomeWiredNameForm = Logger.detached('SomeWiredNameForm'); class SomeWiredNameForm implements FormModel { - SomeWiredNameForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SomeWiredNameForm( + this.form, + this.path, + this._formModel, { + RenamedBasic? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -244,8 +251,10 @@ class SomeWiredNameForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + RenamedBasic? _ownInitialModel; + + late Map _ownInitialRawValue = + SomeWiredNameForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -476,10 +485,28 @@ class SomeWiredNameForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + RenamedBasic? get initialModel { + return _ownInitialModel; + } + + void commitInitial([RenamedBasic? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SomeWiredNameForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -518,55 +545,6 @@ class SomeWiredNameForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_output.gform.dart index 2d13e474..42696025 100644 --- a/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/renamed_basic/renamed_basic_output.gform.dart @@ -151,6 +151,7 @@ class _SomeWiredNameFormBuilderState extends State { SomeWiredNameForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _SomeWiredNameFormBuilderState extends State { @override void didUpdateWidget(covariant SomeWiredNameFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -229,8 +232,12 @@ final _logSomeWiredNameForm = Logger.detached('SomeWiredNameForm'); class SomeWiredNameForm implements FormModel { - SomeWiredNameForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SomeWiredNameForm( + this.form, + this.path, + this._formModel, { + RenamedBasicO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -245,8 +252,10 @@ class SomeWiredNameForm final Map _disabled = {}; - @override - final Map initial; + RenamedBasicO? _ownInitialModel; + + late Map _ownInitialRawValue = + SomeWiredNameForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -525,10 +534,28 @@ class SomeWiredNameForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + RenamedBasicO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([RenamedBasicO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SomeWiredNameForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -567,55 +594,6 @@ class SomeWiredNameForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); 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 37c60ae2..171a4f0d 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 @@ -149,6 +149,7 @@ class _UserProfileFormBuilderState extends State { UserProfileForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -191,7 +192,9 @@ class _UserProfileFormBuilderState extends State { @override void didUpdateWidget(covariant UserProfileFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -226,8 +229,12 @@ class _UserProfileFormBuilderState extends State { final _logUserProfileForm = Logger.detached('UserProfileForm'); class UserProfileForm implements FormModel { - UserProfileForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UserProfileForm( + this.form, + this.path, + this._formModel, { + UserProfile? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -248,8 +255,11 @@ class UserProfileForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UserProfile? _ownInitialModel; + + late Map _ownInitialRawValue = UserProfileForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -750,10 +760,28 @@ class UserProfileForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UserProfile? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UserProfile? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UserProfileForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -792,55 +820,6 @@ class UserProfileForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -883,7 +862,8 @@ class UserProfileForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -900,8 +880,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1283,10 +1266,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1325,55 +1324,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile_output.gform.dart b/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile_output.gform.dart index e3629246..f17fad02 100644 --- a/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile_output.gform.dart +++ b/packages/reactive_forms_generator/example/lib/docs/user_profile/user_profile_output.gform.dart @@ -151,6 +151,7 @@ class _UserProfileOFormBuilderState extends State { UserProfileOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -193,7 +194,9 @@ class _UserProfileOFormBuilderState extends State { @override void didUpdateWidget(covariant UserProfileOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -228,8 +231,12 @@ class _UserProfileOFormBuilderState extends State { final _logUserProfileOForm = Logger.detached('UserProfileOForm'); class UserProfileOForm implements FormModel { - UserProfileOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UserProfileOForm( + this.form, + this.path, + this._formModel, { + UserProfileO? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -250,8 +257,11 @@ class UserProfileOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UserProfileO? _ownInitialModel; + + late Map _ownInitialRawValue = UserProfileOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -801,10 +811,28 @@ class UserProfileOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UserProfileO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UserProfileO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UserProfileOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -843,55 +871,6 @@ class UserProfileOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -934,7 +913,8 @@ class UserProfileOForm implements FormModel { final _logAddressOForm = Logger.detached('AddressOForm'); class AddressOForm implements FormModel { - AddressOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressOForm(this.form, this.path, this._formModel, {AddressO? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -951,8 +931,11 @@ class AddressOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + AddressO? _ownInitialModel; + + late Map _ownInitialRawValue = AddressOForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1339,10 +1322,26 @@ class AddressOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AddressO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AddressO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1381,55 +1380,6 @@ class AddressOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_generator/example/lib/widgets/dirty_badge.dart b/packages/reactive_forms_generator/example/lib/widgets/dirty_badge.dart new file mode 100644 index 00000000..743e9b1b --- /dev/null +++ b/packages/reactive_forms_generator/example/lib/widgets/dirty_badge.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class DirtyBadge extends StatelessWidget { + const DirtyBadge({super.key, required this.changed, this.label}); + + final bool changed; + final String? label; + + @override + Widget build(BuildContext context) { + final color = changed ? Colors.orange.shade700 : Colors.grey.shade400; + final label = this.label; + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + changed ? Icons.circle : Icons.circle_outlined, + size: 10, + color: color, + ), + if (label != null) ...[ + const SizedBox(width: 4), + Text(label, style: TextStyle(color: color, fontSize: 11)), + ], + ], + ); + } +} diff --git a/packages/reactive_forms_generator/example/test/doc/delivery_list/delivery_list_dirty_test.dart b/packages/reactive_forms_generator/example/test/doc/delivery_list/delivery_list_dirty_test.dart new file mode 100644 index 00000000..66dadc00 --- /dev/null +++ b/packages/reactive_forms_generator/example/test/doc/delivery_list/delivery_list_dirty_test.dart @@ -0,0 +1,215 @@ +import 'package:example/docs/delivery_list/delivery_list.dart'; +import 'package:flutter_test/flutter_test.dart'; + +DeliveryListForm buildForm(DeliveryList model) => DeliveryListForm( + DeliveryListForm.formElements(model), + null, + null, + initialModel: model, +); + +const seed = DeliveryList( + deliveryList: [ + DeliveryPoint(name: 'n1', address: Address(street: 's1', city: 'c1')), + DeliveryPoint(name: 'n2', address: Address(street: 's2', city: 'c2')), + ], + clientList: [], +); + +void main() { + group('DeliveryList hasChanged semantics', () { + test('fresh form is clean at every level', () { + final f = buildForm(seed); + + expect(f.hasChanged, isFalse); + expect(f.deliveryListDeliveryPointForm[0].hasChanged, isFalse); + expect( + f.deliveryListDeliveryPointForm[0].addressForm.hasChanged, + isFalse, + ); + expect(f.deliveryListDeliveryPointForm[1].hasChanged, isFalse); + }); + + test('editing a nested street flips root + item + address', () { + final f = buildForm(seed); + + f.deliveryListDeliveryPointForm[0].addressForm.streetControl.updateValue( + 'EDITED', + ); + + expect(f.hasChanged, isTrue); + expect(f.deliveryListDeliveryPointForm[0].hasChanged, isTrue); + expect( + f.deliveryListDeliveryPointForm[0].addressForm.hasChanged, + isTrue, + ); + expect(f.deliveryListDeliveryPointForm[1].hasChanged, isFalse); + expect( + f.deliveryListDeliveryPointForm[1].addressForm.hasChanged, + isFalse, + ); + }); + + test('restoring the edited value returns to clean', () { + final f = buildForm(seed); + final address = f.deliveryListDeliveryPointForm[0].addressForm; + + address.streetControl.updateValue('EDITED'); + expect(f.hasChanged, isTrue); + + address.streetControl.updateValue('s1'); + expect(f.hasChanged, isFalse); + expect(address.hasChanged, isFalse); + }); + + test('clearing a nullable String control (null seed) returns to clean', () { + final f = buildForm( + const DeliveryList( + deliveryList: [DeliveryPoint(name: 'x')], // address null + ), + ); + final address = f.deliveryListDeliveryPointForm[0].addressForm; + + expect(f.hasChanged, isFalse); + + address.streetControl.updateValue('X'); + expect(f.hasChanged, isTrue); + + address.streetControl.updateValue(null); + expect( + f.hasChanged, + isFalse, + reason: + 'restoring a nullable String to its seeded null must flip back ' + 'to clean', + ); + }); + + test('toggling disabled is not a value change', () { + final f = buildForm(seed); + + f.deliveryListDeliveryPointForm[0].toggleDisabled(); + expect(f.hasChanged, isFalse); + + f.deliveryListDeliveryPointForm[0].toggleDisabled(); + expect(f.hasChanged, isFalse); + }); + + test('adding an item flips root dirty (structural change)', () { + final f = buildForm(seed); + + f.addDeliveryListItem( + const DeliveryPoint( + name: 'n3', + address: Address(street: 's3', city: 'c3'), + ), + ); + + expect(f.hasChanged, isTrue); + // The two pre-existing items must stay clean. + expect(f.deliveryListDeliveryPointForm[0].hasChanged, isFalse); + expect(f.deliveryListDeliveryPointForm[1].hasChanged, isFalse); + // The new item has no baseline slice, so it is dirty. + expect(f.deliveryListDeliveryPointForm[2].hasChanged, isTrue); + }); + + test('adding 3 empty items flips root dirty', () { + final f = buildForm(seed); + + for (var i = 0; i < 3; i++) { + f.addDeliveryListItem(const DeliveryPoint()); + } + + expect(f.hasChanged, isTrue); + }); + + test('removing the last item flips root dirty', () { + final f = buildForm(seed); + + f.removeDeliveryListItemAtIndex(1); + + expect(f.hasChanged, isTrue); + expect(f.deliveryListDeliveryPointForm[0].hasChanged, isFalse); + }); + + test('commitInitial after edit returns everything to clean', () { + final f = buildForm(seed); + + f.deliveryListDeliveryPointForm[0].nameControl.updateValue('edited'); + f.addDeliveryListItem( + const DeliveryPoint(name: 'n3', address: Address(street: 's3')), + ); + + expect(f.hasChanged, isTrue); + + f.commitInitial(); + + expect(f.hasChanged, isFalse); + expect(f.deliveryListDeliveryPointForm[0].hasChanged, isFalse); + expect(f.deliveryListDeliveryPointForm[1].hasChanged, isFalse); + expect(f.deliveryListDeliveryPointForm[2].hasChanged, isFalse); + }); + + test('equalsTo at root compares against arbitrary model', () { + final f = buildForm(seed); + + expect(f.equalsTo(seed), isTrue); + expect( + f.equalsTo( + const DeliveryList( + deliveryList: [DeliveryPoint(name: 'other')], + clientList: [], + ), + ), + isFalse, + ); + }); + + test('equalsTo on a nested item compares only its slice', () { + final f = buildForm(seed); + final i0 = f.deliveryListDeliveryPointForm[0]; + + expect( + i0.equalsTo( + const DeliveryPoint( + name: 'n1', + address: Address(street: 's1', city: 'c1'), + ), + ), + isTrue, + ); + + f.deliveryListDeliveryPointForm[0].nameControl.updateValue('mutated'); + // Re-read nested form after mutation. + final i0After = f.deliveryListDeliveryPointForm[0]; + expect( + i0After.equalsTo( + const DeliveryPoint( + name: 'n1', + address: Address(street: 's1', city: 'c1'), + ), + ), + isFalse, + ); + }); + + test('initialModel getter exposes the typed baseline on the root', () { + final f = buildForm(seed); + expect(f.initialModel, equals(seed)); + + f.deliveryListDeliveryPointForm[0].nameControl.updateValue('mutated'); + expect( + f.initialModel, + equals(seed), + reason: 'initialModel must stay frozen across edits', + ); + + f.commitInitial(); + expect( + f.initialModel?.deliveryList.first.name, + equals('mutated'), + reason: 'commitInitial must adopt the current rawModel', + ); + }); + }); +} diff --git a/packages/reactive_forms_generator/lib/src/form_generator.dart b/packages/reactive_forms_generator/lib/src/form_generator.dart index 6b2226cc..16068404 100644 --- a/packages/reactive_forms_generator/lib/src/form_generator.dart +++ b/packages/reactive_forms_generator/lib/src/form_generator.dart @@ -638,8 +638,8 @@ class FormGenerator { Code get logging => Code("final $log = Logger.detached('$classNameFull');"); - Constructor get _constructor => Constructor( - (b) => b + Constructor get _constructor => Constructor((b) { + b ..requiredParameters.addAll([ Parameter( (b) => b @@ -657,8 +657,16 @@ class FormGenerator { ..toThis = true, ), ]) - ..initializers.add(const Code('initial = form.rawValue')), - ); + ..optionalParameters.add( + Parameter( + (p) => p + ..name = 'initialModel' + ..named = true + ..type = Reference('${element.fullTypeName}?'), + ), + ) + ..initializers.add(const Code('_ownInitialModel = initialModel')); + }); String get _modelDisplayTypeNonNullable { String displayType = @@ -799,9 +807,16 @@ class FormGenerator { ), Field( (b) => b - ..name = 'initial' - ..annotations.add(const CodeExpression(Code('override'))) - ..modifier = FieldModifier.final$ + ..name = '_ownInitialModel' + ..type = Reference('${element.fullTypeName}?'), + ), + Field( + (b) => b + ..name = '_ownInitialRawValue' + ..late = true + ..assignment = Code( + '$className.formElements(_ownInitialModel).rawValue', + ) ..type = const Reference('Map'), ), ]) @@ -843,80 +858,50 @@ class FormGenerator { ..body = const Code(''' return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); '''), ), - currentFormMethod, - updateValueMethod, - upsertValueMethod, - resetMethod, Method( (b) => b - ..name = 'updateInitial' - ..lambda = false + ..name = 'initialRawValue' + ..type = MethodType.getter ..annotations.add(const CodeExpression(Code('override'))) - ..requiredParameters.addAll([ - Parameter( - (b) => b - ..name = 'value' - ..type = const Reference('Map?'), - ), + ..returns = const Reference('Map') + ..body = const Code(''' + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + '''), + ), + Method( + (b) => b + ..name = 'initialModel' + ..type = MethodType.getter + ..returns = Reference('${element.fullTypeName}?') + ..body = const Code('return _ownInitialModel;'), + ), + Method( + (b) => b + ..name = 'commitInitial' + ..returns = const Reference('void') + ..optionalParameters.add( Parameter( - (b) => b - ..name = 'path' - ..type = const Reference('String?'), + (p) => p + ..name = 'newModel' + ..type = Reference('${element.fullTypeName}?'), ), - ]) - ..returns = const Reference('void') - ..body = const Code(''' - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } + ) + ..body = Code(''' + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = + $className.formElements(_ownInitialModel).rawValue; '''), ), + currentFormMethod, + updateValueMethod, + upsertValueMethod, + resetMethod, Method( (b) => b ..name = 'pathBuilder' diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_builder.dart b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_builder.dart index 9e34a422..a75c6698 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_builder.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms/reactive_form_builder.dart @@ -158,7 +158,7 @@ class ReactiveFormBuilder { ..annotations.add(const CodeExpression(Code('override'))) ..returns = const Reference('void') ..body = Code(''' - _formModel = ${reactiveForm.reactiveInheritedStreamer.formGenerator.classNameFull}(${reactiveForm.reactiveInheritedStreamer.formGenerator.className}.formElements${reactiveForm.reactiveInheritedStreamer.formGenerator.element.generics}(widget.model), null, null); + _formModel = ${reactiveForm.reactiveInheritedStreamer.formGenerator.classNameFull}(${reactiveForm.reactiveInheritedStreamer.formGenerator.className}.formElements${reactiveForm.reactiveInheritedStreamer.formGenerator.element.generics}(widget.model), null, null, initialModel: widget.model); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -212,9 +212,11 @@ class ReactiveFormBuilder { ) ..body = const Code(''' if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } - + super.didUpdateWidget(oldWidget); '''), ), diff --git a/packages/reactive_forms_generator/pubspec.yaml b/packages/reactive_forms_generator/pubspec.yaml index fcd9cf5c..32d13391 100644 --- a/packages/reactive_forms_generator/pubspec.yaml +++ b/packages/reactive_forms_generator/pubspec.yaml @@ -2,7 +2,7 @@ name: reactive_forms_generator description: Generator for reactive_forms. Generates form classes based on model. repository: https://github.com/artflutter/reactive_forms_generator -version: 8.3.1 +version: 8.4.0 environment: sdk: ">=3.8.0 <4.0.0"