From 987768feb25ce9a8d2adadb48fa7e8f66b0fb8fc Mon Sep 17 00:00:00 2001 From: Joan Pablo Date: Mon, 21 Aug 2023 13:10:13 -0400 Subject: [PATCH 1/4] Add markAsPending to controls issue #274 - Allow to mark an abstract control as pending by demand. --- CHANGELOG.md | 7 +++++++ lib/src/models/models.dart | 24 ++++++++++++++++++++++++ test/src/models/form_array_test.dart | 18 ++++++++++++++++++ test/src/models/form_control_test.dart | 15 +++++++++++++++ test/src/models/form_group_test.dart | 18 ++++++++++++++++++ 5 files changed, 82 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 131bbda..9b87a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 16.1.0 + +## Features + +- Add `markAsPending()` method to `AbstractControl` to allow set the status +to PENDING by demand. + # 16.0.4 ## Fixes diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart index 79e1e65..e2e0532 100644 --- a/lib/src/models/models.dart +++ b/lib/src/models/models.dart @@ -228,6 +228,8 @@ abstract class AbstractControl { /// * VALID: This control has passed all validation checks. /// * INVALID: This control has failed at least one validation check. /// * PENDING: This control is in the midst of conducting a validation check. + /// * DISABLED: This control is exempt from ancestor calculations of + /// validity or value. /// /// These status values are mutually exclusive, so a control cannot be both /// valid AND invalid or invalid AND pending. @@ -420,6 +422,28 @@ abstract class AbstractControl { _updateAncestors(updateParent); } + /// Marks the control as `pending`. + /// + /// A control is pending while the control performs async validation. + /// + /// When [updateParent] is false, mark only this control. When true or not + /// supplied, marks all direct ancestors. Default is true. + /// + /// When [emitEvent] is true or not supplied (the default), a [statusChanged] + /// event is emitted. + /// + void markAsPending({bool updateParent = true, bool emitEvent = true}) { + _status = ControlStatus.pending; + + if (emitEvent) { + this._statusChanges.add(_status); + } + + if (updateParent) { + parent?.markAsPending(updateParent: updateParent, emitEvent: emitEvent); + } + } + /// Disposes the control void dispose() { _statusChanges.close(); diff --git a/test/src/models/form_array_test.dart b/test/src/models/form_array_test.dart index 6ee26a7..fc05df3 100644 --- a/test/src/models/form_array_test.dart +++ b/test/src/models/form_array_test.dart @@ -716,6 +716,24 @@ void main() { // Then: array value is patched expect(array.value, [2, 2], reason: 'array value not patched'); }); + + test('Test that markAsPending() a control, set pending status to the array ' + 'as well.', () { + // Given: an array with valid status. + final array = FormArray([ + FormControl(value: 1), + ]); + + // Expect: the array to be VALID and not PENDING. + expect(array.valid, true); + expect(array.pending, false); + + // When: I call mark a child control as PENDING. + array.controls.first.markAsPending(); + + // Then: the status of the array is PENDING as well. + expect(array.pending, true); + }); }); } diff --git a/test/src/models/form_control_test.dart b/test/src/models/form_control_test.dart index ad66f6e..6ce5186 100644 --- a/test/src/models/form_control_test.dart +++ b/test/src/models/form_control_test.dart @@ -371,5 +371,20 @@ void main() { // Then: a new async validator is added expect(formControl.asyncValidators.length, 1); }); + + test('Test that markAsPending() change the status to PENDING.', () { + // Given: a control with valid status. + final control = FormControl(value: 'Reactive Forms'); + + // Expect: the control to be VALID and not PENDING. + expect(control.valid, true); + expect(control.pending, false); + + // When: I call markAsPending() method. + control.markAsPending(); + + // Then: the status is PENDING. + expect(control.pending, true); + }); }); } diff --git a/test/src/models/form_group_test.dart b/test/src/models/form_group_test.dart index a8e5b66..c1016bc 100644 --- a/test/src/models/form_group_test.dart +++ b/test/src/models/form_group_test.dart @@ -982,5 +982,23 @@ void main() { // Expect: an assertion error expect(form, throwsAssertionError); }); + + test('Test that markAsPending() a control, set pending status to the group ' + 'as well.', () { + // Given: a form group with valid status. + final form = FormGroup({ + 'name': FormControl(value: "Reactive Forms") + }); + + // Expect: the group to be VALID and not PENDING. + expect(form.valid, true); + expect(form.pending, false); + + // When: I call mark a child control as PENDING. + form.control('name').markAsPending(); + + // Then: the status of the Form Group is PENDING as well. + expect(form.pending, true); + }); }); } From 850ab542df07d0ec8035e98164843d4282c611c5 Mon Sep 17 00:00:00 2001 From: Joan Pablo Date: Mon, 21 Aug 2023 13:10:13 -0400 Subject: [PATCH 2/4] Add markAsPending to controls issue #274 - Allow to mark an abstract control as pending by demand. --- CHANGELOG.md | 7 +++++++ lib/src/models/models.dart | 24 ++++++++++++++++++++++++ test/src/models/form_array_test.dart | 19 +++++++++++++++++++ test/src/models/form_control_test.dart | 15 +++++++++++++++ test/src/models/form_group_test.dart | 18 ++++++++++++++++++ 5 files changed, 83 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 131bbda..9b87a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 16.1.0 + +## Features + +- Add `markAsPending()` method to `AbstractControl` to allow set the status +to PENDING by demand. + # 16.0.4 ## Fixes diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart index 79e1e65..0040ea7 100644 --- a/lib/src/models/models.dart +++ b/lib/src/models/models.dart @@ -228,6 +228,8 @@ abstract class AbstractControl { /// * VALID: This control has passed all validation checks. /// * INVALID: This control has failed at least one validation check. /// * PENDING: This control is in the midst of conducting a validation check. + /// * DISABLED: This control is exempt from ancestor calculations of + /// validity or value. /// /// These status values are mutually exclusive, so a control cannot be both /// valid AND invalid or invalid AND pending. @@ -420,6 +422,28 @@ abstract class AbstractControl { _updateAncestors(updateParent); } + /// Marks the control as `pending`. + /// + /// A control is pending while the control performs async validation. + /// + /// When [updateParent] is false, mark only this control. When true or not + /// supplied, marks all direct ancestors. Default is true. + /// + /// When [emitEvent] is true or not supplied (the default), a [statusChanged] + /// event is emitted. + /// + void markAsPending({bool updateParent = true, bool emitEvent = true}) { + _status = ControlStatus.pending; + + if (emitEvent) { + this._statusChanges.add(_status); + } + + if (updateParent) { + parent?.markAsPending(updateParent: updateParent, emitEvent: emitEvent); + } + } + /// Disposes the control void dispose() { _statusChanges.close(); diff --git a/test/src/models/form_array_test.dart b/test/src/models/form_array_test.dart index 6ee26a7..d081ce1 100644 --- a/test/src/models/form_array_test.dart +++ b/test/src/models/form_array_test.dart @@ -716,6 +716,25 @@ void main() { // Then: array value is patched expect(array.value, [2, 2], reason: 'array value not patched'); }); + + test( + 'Test that markAsPending() a control, set pending status to the array ' + 'as well.', () { + // Given: an array with valid status. + final array = FormArray([ + FormControl(value: 1), + ]); + + // Expect: the array to be VALID and not PENDING. + expect(array.valid, true); + expect(array.pending, false); + + // When: I call mark a child control as PENDING. + array.controls.first.markAsPending(); + + // Then: the status of the array is PENDING as well. + expect(array.pending, true); + }); }); } diff --git a/test/src/models/form_control_test.dart b/test/src/models/form_control_test.dart index ad66f6e..6ce5186 100644 --- a/test/src/models/form_control_test.dart +++ b/test/src/models/form_control_test.dart @@ -371,5 +371,20 @@ void main() { // Then: a new async validator is added expect(formControl.asyncValidators.length, 1); }); + + test('Test that markAsPending() change the status to PENDING.', () { + // Given: a control with valid status. + final control = FormControl(value: 'Reactive Forms'); + + // Expect: the control to be VALID and not PENDING. + expect(control.valid, true); + expect(control.pending, false); + + // When: I call markAsPending() method. + control.markAsPending(); + + // Then: the status is PENDING. + expect(control.pending, true); + }); }); } diff --git a/test/src/models/form_group_test.dart b/test/src/models/form_group_test.dart index a8e5b66..72b9dd7 100644 --- a/test/src/models/form_group_test.dart +++ b/test/src/models/form_group_test.dart @@ -982,5 +982,23 @@ void main() { // Expect: an assertion error expect(form, throwsAssertionError); }); + + test( + 'Test that markAsPending() a control, set pending status to the group ' + 'as well.', () { + // Given: a form group with valid status. + final form = + FormGroup({'name': FormControl(value: "Reactive Forms")}); + + // Expect: the group to be VALID and not PENDING. + expect(form.valid, true); + expect(form.pending, false); + + // When: I call mark a child control as PENDING. + form.control('name').markAsPending(); + + // Then: the status of the Form Group is PENDING as well. + expect(form.pending, true); + }); }); } From 99a5871b982a2f6484ee80a162fd8bf575d54e78 Mon Sep 17 00:00:00 2001 From: Joan Pablo Date: Mon, 21 Aug 2023 13:32:20 -0400 Subject: [PATCH 3/4] Update flutter actions dependencies --- .github/workflows/reactive_forms.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/reactive_forms.yaml b/.github/workflows/reactive_forms.yaml index 1f98432..a99023f 100644 --- a/.github/workflows/reactive_forms.yaml +++ b/.github/workflows/reactive_forms.yaml @@ -20,8 +20,8 @@ jobs: # This job runs on Linux runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: subosito/flutter-action@v1 + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 with: flutter-version: "3.10.0" channel: "stable" @@ -33,8 +33,8 @@ jobs: name: Analyze runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: subosito/flutter-action@v1 + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 with: flutter-version: "3.10.0" channel: "stable" @@ -48,8 +48,8 @@ jobs: name: Format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: subosito/flutter-action@v1 + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 with: flutter-version: "3.10.0" channel: "stable" From f4c51c06d410e69d71042ef5e5d3a8c21755c122 Mon Sep 17 00:00:00 2001 From: Joan Pablo Date: Mon, 21 Aug 2023 13:53:43 -0400 Subject: [PATCH 4/4] Release v16.1.0 --- README.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3faf227..9b52429 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ dependencies: flutter: sdk: flutter - reactive_forms: ^16.0.4 + reactive_forms: ^16.1.0 ``` Then run the command `flutter packages get` on the console. diff --git a/pubspec.yaml b/pubspec.yaml index 0fe107d..081c17d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: reactive_forms description: This is a model-driven approach to handling form inputs and validations, heavily inspired in Angular Reactive Forms. -version: 16.0.4 +version: 16.1.0 homepage: "https://github.com/joanpablo/reactive_forms" environment: