-
Notifications
You must be signed in to change notification settings - Fork 0
Add ComposedGladeModel and related components for multi-forms support #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
183d0b6
Add ComposedGladeModel and related components for multi-forms support
3ddb2f2
Implement ComposedGladeModel and related components for dynamic form …
0fcb4e5
Add GladeComposedModelListener for stateful model updates in forms
8cdd06a
Refactor ComposedGladeModel to GladeComposedModel and update related …
202debf
Add GladeComposedFormConsumer and GladeComposedFormListener for impro…
90fec9c
Fix conditional structure in GladeComposedListBuilder for improved va…
68150d2
Refactor CHANGELOG to update entries for GladeComposedModel and relat…
3a19a96
Update composed model GIF asset to reflect recent changes
f15ecdf
Refactor GladeModel to support multiple bound composed models and upd…
b889077
Merge branch 'main' into story/96-composed-glade-model
961740d
Refactor Glade model architecture to support nested composed models a…
15b65ca
Refactor GladeModel and GladeModelBase to replace private _lastUpdate…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| --- | ||
| title: Composed forms | ||
| description: Building dynamic lists of forms | ||
| --- | ||
|
|
||
| Composed forms are ideal when you need to manage multiple instances of the same form. The number of forms doesn’t need to be known in advance — new instances can be added or removed at any time. | ||
|
|
||
| The core building block of this system is the `GladeComposedModel`, which maintains and manages a list of individual `GladeModel` or even another `GladeComposedModel` instances contained within the composed form. | ||
|
|
||
| Because `GladeComposedModel` extends `ChangeNotifier`, any dependent widgets automatically rebuild when the model changes. | ||
|
|
||
| **Using a composed model** | ||
|
|
||
| Composed models behave just like ordinary `GladeModel` objects — they are even provided with the same `GladeModelProvider` and consumed with `GladeFormBuilder`: | ||
|
|
||
| ```dart | ||
| GladeModelProvider( | ||
| create: (context) => MyComposedModel([MyFormModel()]), | ||
| child: GladeFormBuilder<MyComposedModel>( | ||
| builder: (context, composedModel, child) => ... | ||
| ), | ||
| ) | ||
| ``` | ||
|
|
||
| **Managing contained models** | ||
|
|
||
| You can dynamically add or remove form models: | ||
|
|
||
| ```dart | ||
| composedModel.addModel(model); | ||
| composedModel.removeModel(model); | ||
| ``` | ||
|
|
||
| Whenever any contained form model changes — or a model is added or removed — the entire composed form builder rebuilds to reflect the updated list. | ||
|
|
||
| **Rendering multiple identical forms** | ||
|
|
||
| Since all form models within a composed model share the same type, it's often helpful to automatically generate the same form widget for each model. This is where `GladeComposedListBuilder` comes in. It iterates through all models and builds the appropriate form widget for each one. | ||
|
|
||
|  |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| import 'package:glade_forms/src/src.dart'; | ||
|
|
||
| import 'package:glade_forms/src/validator/validator_result.dart'; | ||
|
|
||
| abstract class GladeComposedModel<M extends GladeModelBase> extends GladeModelBase { | ||
| final List<M> _models = []; | ||
|
|
||
| /// Returns true if all models are valid. | ||
| @override | ||
| bool get isValid => models.every((model) => model.isValid); | ||
|
|
||
| @override | ||
| bool get isValidWithoutWarnings => models.every((model) => model.isValidWithoutWarnings); | ||
|
|
||
| @override | ||
| bool get isPure => models.every((model) => model.isPure); | ||
|
|
||
| /// Returns true if model is not pure. | ||
| @override | ||
| bool get isDirty => !isPure; | ||
|
|
||
| /// Returns true if all models have unchanged inputs. | ||
| /// | ||
| /// Input is unchanged if its value is same as initial value, even if value was updated into initial value. | ||
| @override | ||
| bool get isUnchanged => models.every((model) => model.isUnchanged); | ||
|
|
||
| /// Models that this composed model is currently listening to. | ||
| List<M> get models => _models; | ||
|
|
||
| @override | ||
| List<ValidatorResult<Object?>> get validatorResults => [ | ||
| for (final e in models) ...e.validatorResults, | ||
| ]; | ||
|
|
||
| /// Constructor can take form models to start with. | ||
| GladeComposedModel([List<M>? initialModels]) { | ||
| if (initialModels != null) { | ||
| for (final model in initialModels) { | ||
| addModel(model); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Adds model to `models` list. | ||
| /// Whenever form model changes, it triggers also change on this composed model. | ||
| void addModel(M model) { | ||
| _models.add(model); | ||
| model | ||
| ..addListener(notifyListeners) | ||
| ..bindToComposedModel(this); | ||
| notifyListeners(); | ||
| } | ||
|
|
||
| /// Removes model from `models` list. | ||
| /// Also unregisters from listening to its changes. | ||
| void removeModel(M model) { | ||
| final _ = _models.remove(model); | ||
| model | ||
| ..removeListener(notifyListeners) | ||
| ..unbindFromComposedModel(this); | ||
| notifyListeners(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:glade_forms/src/src.dart'; | ||
| import 'package:glade_forms/src/validator/validator_result.dart'; | ||
|
|
||
| abstract class GladeModelBase extends ChangeNotifier { | ||
| List<GladeInput<Object?>> lastUpdates = []; | ||
| final List<GladeComposedModel> _bindedComposeModels = []; | ||
|
|
||
| bool get isValid; | ||
|
|
||
| bool get isValidWithoutWarnings; | ||
|
|
||
| bool get isPure; | ||
|
|
||
| bool get isUnchanged; | ||
|
|
||
| List<ValidatorResult<Object?>> get validatorResults; | ||
|
|
||
| bool get isNotValid => !isValid; | ||
|
|
||
| bool get isDirty => !isPure; | ||
|
|
||
| List<String> get lastUpdatedInputKeys => lastUpdates.map((e) => e.inputKey).toList(); | ||
|
|
||
| /// Binds current model to compose model. | ||
| void bindToComposedModel(GladeComposedModel model) { | ||
| _bindedComposeModels.add(model); | ||
| } | ||
|
|
||
| /// Unbinds current model from compose model. | ||
| bool unbindFromComposedModel(GladeComposedModel model) { | ||
| return _bindedComposeModels.remove(model); | ||
| } | ||
|
|
||
| @override | ||
| void dispose() { | ||
| for (final composeModel in _bindedComposeModels) { | ||
| composeModel.removeModel(this); | ||
| } | ||
| super.dispose(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,4 @@ | ||
| export 'glade_composed_model.dart'; | ||
| export 'glade_metadata.dart'; | ||
| export 'glade_model.dart'; | ||
| export 'glade_model_base.dart'; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.