glade_forms 7.0.0
glade_forms: ^7.0.0 copied to clipboard
A universal way to define form validators with support of translations.
7.0.0 #
- Breaking:
GladeComposedModelnewly inherits members ofGladeInputsOwner(initialize,inputs,updateInput, ...). A same-named member in your subclass is now an override - see the composed model's own inputs entry below. - [Add]: Asynchronous validation (#12).
- New validator parts
satisfyAsync()andcustomAsync()withrunOnlyWhenSyncValidandonErroroptions;build(asyncDebounce:)configures debounce (default 300 ms). GladeInputgainsisValidating,hasAsyncValidationandvalidateAsync({force}). Validation requests (validate(),textFormFieldInputValidator,formFieldValidator, value changes) trigger async validation; getters only read.ValidatorResultgainsasyncState(notRun,debouncing,running,done),asyncValidatedValue,isValidatingandisAsyncValidationRunning.isValidatingcovers the debounce window and the request;isAsyncValidationRunningcovers only a request in flight, so a loading indicator does not flicker while typing.- Only asynchronous results are cached - the synchronous half is recomputed on every read, so a synchronous validator reading a dependency is never masked by a cached result.
- A failed request is reported but retried by an explicit
validateAsync(); passive triggers do not retry it.ValidatorResultis now exported from the package. asyncValidationMode(strictdefault,lastKnown) decides how pending async validation affectsisValid. It lives onGladeInputsOwner, soGladeModelandGladeComposedModelboth honour it, and both exposeisValidating,isAsyncValidationRunningandvalidateAsync().AsyncValidationFailedErrorwith keyGladeValidationsKeys.asyncValidationFailedreports exceptions from async validators;DefaultValidationTranslations.defaultAsyncValidationFailedMessageprovides a fallback message.GladeComposedModelsupports async validation on its own inputs and aggregates both levels:isValidating,isAsyncValidationRunningandvalidateAsync()cover own inputs together with the contained models.asyncValidationModeis per owner - own inputs follow the composed model, contained models keep their own.- A cached result never reports
donewhile a retry is in flight, and it carries the value its asynchronous parts actually ran against. - The form field validators respect
valueTransform- without it a transformed value never matched the field's text and async validation was never triggered from a form field. - An asynchronous state change clears
lastUpdates, so a listener readinglastUpdatedInputKeysdoes not see the last edit replayed once per state change. validateAsync()on a model lets every input settle instead of failing fast on the first throwing validator.- A cached asynchronous result is tied to the set of parts which produced it, so a result produced while synchronous validation was failing is not reused once it passes.
- Cached results are dropped on a structural value change. Where a text field is the source of the value, the text decides instead, so a cursor move does not restart validation and the field's own text counts as the current value.
GladeModelBasegainedisValidating,isAsyncValidationRunningandvalidateAsync(), all with defaults, so extending it directly keeps compiling.ValidatorInstance.hasDeclaredValidator()keeps reporting synchronous parts only; asynchronous ones are reported by the newhasDeclaredAsyncValidator().GladeFormDebugInfoand the DevTools extension show async validation state.
- New validator parts
- [Add]:
GladeComposedModelcan have inputs of its own, next to the models it contains (#106).- Declare them as on
GladeModel- create the inputs ininitialize()and list them ininputs. Overridinginitialize()is optional for a composed model. - Own inputs are aggregated together with the contained models into
isValid,isValidWithoutWarnings,isPure,isUnchangedandvalidatorResults. A composed model without own inputs behaves exactly as before. resetToInitialValue()andsetInputValuesAsNewInitialValues()on a composed model reach its own inputs and every contained model.- Composed-level inputs and inputs of contained models do not observe each other - neither direction of a cross-level dependency is notified. See the docs.
- Beware:
GladeComposedModelnewly inherits these members, so a same-named member in your subclass is now an override:inputs,allInputs,initialize,bindToModel,updateInput,stringFieldUpdateInput,groupEdit,isGroupEditing,notifyDependencies,resetToInitialValue,setInputValuesAsNewInitialValues,fillDebugMetadata,hasDebugMetadata,formattedValidationErrors,formattedValidationErrorsAndWarnings,debugFormattedValidationErrors,defaultValidationTranslate.- A member whose signature is not a valid override is a compile error, so you will see it. Two shapes are silent and deserve a check:
- A method named
initialize()(includingFuture<void> initialize(), which is a valid override) now overrides the new hook and is invoked from the constructor - rename it, or callsuper.initialize()last. - A getter named
inputsreturning a flattened list of contained models' inputs is now an override of the own-inputs contract, andaddModel()will assert. List only the composed model's own inputs.
- Declare them as on
- [Add]: New
GladeInputsOwnermixin carries the input ownership shared byGladeModelandGladeComposedModel. Every member remains available on both classes with an unchanged signature; onlyGladeInput.bindToModel(@internal) accepts the mixin instead ofGladeModel.GladeFormDebugInfoandGladeFormDebugInfoModal.showare bound toGladeInputsOwner, so they accept a composed model as well.GladeFormDebugInfoalso shows how many models a composed model contains and how many of them are not valid.
- [Add]: DevTools extension displays composed model's own inputs and counts them next to its child models.
- [Add]: Export
ValidatorResult- it is the element type of the publicvalidatorResults,GladeInput.validatorResult,GladeInput.validate()andChangesInfo.validatorResult, but could not be named by a consumer. - [Fix]:
lastUpdateson a composed model no longer re-broadcasts keys of the previous own-input update when a contained model changes or a model is attached or detached - it is empty for those notifications. - [Fix]:
groupEdit()no longer leaks keys of an update which preceded the batch, so dependencies of inputs which did not change within the batch are not notified anymore.- A notification raised by a contained model during a composed model's
groupEdit()is folded into the single notification the batch emits at its end. Previously it broke the batch in two and dropped the accumulated keys. - A nested
groupEdit()is part of the batch which is already running: it no longer flushes on its own, so one batch notifies exactly once instead of once per nesting level. - Group edit mode is always left and the batch is always flushed, even when the callback throws.
- A notification raised by a contained model during a composed model's
- [Fix]:
updateInput()andstringFieldUpdateInput()no longer announce an update which the input announces itself.- Called within
groupEdit()they used to overwrite everything the batch had accumulated and notify in the middle of it, so keys were lost and dependencies of the lost inputs were never notified. - Outside a batch they now emit one notification per update instead of two.
- Called within
- [Fix]:
resetToInitialValue()andsetInputValuesAsNewInitialValues()on a composed model are batched, so listeners are notified once instead of once per contained model - and never with a form which is half reset. - [Fix]: DevTools serializer produced the key
depedencies, so an input's dependencies were never displayed in the extension. - [Fix]: DevTools serializer wrote
initialValueunencoded, so a single input whose value is not a JSON primitive (e.g.GladeDateTimeInput) made the whole response fail to encode and every model disappeared from the inspector. - [Fix]:
GladeFormDebugInfoModal.show()did not pass its type argument to theGladeFormDebugInfoit builds, so the widget looked up its own bound instead of the model given to it and always threwProviderNotFoundException. - [Fix]:
lastUpdatesis no longer cleared by a nested notification raised while the model is delivering its own update - e.g. when anonDependencyChangecallback updates a contained model. - [Fix]: DevTools extension failed to parse any model which has at least one input - decoded JSON lists were cast directly to
List<String>, which throws even for an empty list. - [Fix]: The DevTools extension is now part of the published package. Versions 6.0.0 to 6.1.0 shipped without its build, so DevTools had no extension to load.
- [Fix]: Own inputs of a composed model are disposed after its contained models are detached and after it detaches from its parent composed models, because both notify synchronously and their listeners may still read those inputs. The disposal can no longer be skipped by a throw.
- A contained model which throws while being disposed no longer stops the disposal of the remaining models - every model is disposed and the collection is cleared, then the first failure is rethrown.
- [Fix]: A model rejected by
addModel()(it shares an input with the composed model) is detached again before the assert fails, so it is never left half attached and driving the composed model. - [Add]:
GladeModelBase.isDisposedtells whether the model was already disposed. - Asserts were added for input ownership: an input can be binded to one model only, an input can not be updated through a model which does not own it, and a composed model can not share an input with a contained model.
- An input which outlived its model - one the model never listed, so it was not disposed with it - can be binded to a new model once the previous owner is disposed.
- A disposed input can not be binded at all: its
TextEditingControlleris gone, so the new model would get a dead input.
- [Fix]: Every
GladeModelthrewBad state: GladeForms.initialize() must be called before using GladeModelin profile mode, althoughGladeForms.initialize()was called.initialize()set up the DevTools registry in debug mode only, while models register with it in every non-release mode.GladeForms.initialize()now sets up DevTools integration in debug and profile mode, so the inspector is available in profile builds too. Release mode is unchanged.
6.1.0 #
- [Add]:
GladeComposedModel.addModel()andremoveModel()acceptshouldNotifyparameter (#104).- Pass
shouldNotify: falseto attach or detach a model without notifying listeners - e.g. when a model is added during widget's build phase. - Models passed into
GladeComposedModel's constructor no longer trigger notification.
- Pass
- [Fix]:
GladeInputnow disposes itsTextEditingControllerwhen the input is disposed (#102).- Externally provided controller (via
textEditingControllerparameter) is not disposed - its owner stays responsible for it. - Repeated
dispose()calls are no-op. NewGladeInput.isDisposedgetter tells whether the input was already disposed.
- Externally provided controller (via
- [Fix]:
GladeModel.dispose()now disposes all its inputs (allInputs).- Be aware that after model's disposal its inputs (and their controllers) must not be used anymore.
6.0.1 #
- [Fix]:
RegexPatterns.emailnow accepts plus-aliases (e.g.user+tag@gmail.com) and TLDs longer than 4 characters (e.g..online,.software). TLD is now restricted to letters only.
6.0.0 #
- Breaking: Upgrade to Flutter SDK 3.38.0
- Change constraint to Dart sdk: ">=3.8.0"
- Breaking: You need to call
GladeForms.initialize()in order to use Glade Forms DevTools extension.- This is required to setup DevTools extension properly.
- Can be called only in debug mode, but does nothing in release mode.
- [Add]: Add DevTools extension!
- Allows to inspect Glade Forms models in Flutter DevTools
- [Add]: Add
debugKeyproperty for developer friendly unique identification of models.debugKeyis a string that identifies the model in a human-readable way.
5.1.0 #
- [Add]: Add
GladeComposedModelto allow multi-forms creation - [Add]: Add
ComposedExampleto demonstrateGladeComposedModelfunctionality - [Add]: Add
NestedComposedExampleto demonstrate nestedGladeComposedModelfunctionality - [Add]: Add
GladeModel.fillDebugMetadata()method to provide debug metadata as key-value pairs.- This metadata is displayed in
GladeModelDebugInfowidget.
- This metadata is displayed in
5.0.0 #
Breaking change release
In order to introduce support for warning level validations, several breaking changes were made:
GladeInputErrorwas renamed toGladeInputValidationto better reflect its purpose.GladeErrorKeyswas renamed toGladeValidationsKeysErrorTranslatorwas renamed toValidationTranslatorto align with the new naming conventionsdevErrorparameter inGladeValidatormethods was renamed todevMessageto maintain consistency.translateErrorparameter was renamed tovalidationTranslatein bothGladeInputandGladeModelto better represent its functionality.DefaultTranslationswas renamed toDefaultValidationTranslationsto clarify its role in the validation process.- Rename
defaultErrorTranslatetodefaultValidationTranslateinGladeModelfor consistency with other renamings.
New features:
GladeInputValidationnow includes anerrorSeverityproperty, which can be eithererrororwarning.- The
GladeValidatorclass was updated to support warning level validations. - The
GladeInputclass was modified to handle warning level validations appropriately - The
GladeModelclass was also updated to manage warning level validations effectively.
4.2.0 #
- Upgrade dependencies
- Upgrade to Flutter SDK 3.35.0
- Change constraint to Dart sdk: ">=3.8.0 <4.0.0"
4.1.2 #
- [Add]: Add
metaDatatoSatisfyPredicatePartandGladeValidator.satisfyPredicate()to allow passing additional data. - [Add]: Add
getMaxLength()inttoGladeStringInputto get maximum length of the string ifmaxLength()standard validator is used.
4.0.2 #
- [Fix]: Fix
ValueTransformin nullable type does not allow null values.
4.0.1 #
- Fix
input.updateValueshouldTriggerOnChangeparameter, so now next updates already triggeronChange.- Add tests.
- Fix code so it is valid Dart 3.6.0 (Flutter 3.27).
4.0.0 #
Breaking change release
-
Specialized versions of inputs such as
IntInputorStringInputwere renamed toGlade*Input. -
Removed specialized version factories. Now specialized versions are sub-classes of GladeInput
- This removes the weird possibility to create calls such as
StringInput.intInput()which in the end threw a runtime exception due to type mismatch.
- This removes the weird possibility to create calls such as
-
Renamed
valueConverterincreate()factory to match internal namestringToValueConverterwhich is more explicit -
Rename
resetToPure()toresetToInitialValue() -
Change
setAsNewPuretosetNewInitialValue()- Updates input to new initial value
- Optionally input's value can be reset into new initial value (
shouldResetToInitialValueargument).
-
On Model level
- Rename
resetToPure()toresetToInitialValue() - Change
setAsNewPuretosetInputValuesAsNewInitialValues()- Updates all inputs to new initial value
- Optionally input's value can be reset into new initial value (
shouldResetToInitialValueargument).
- Rename
-
Rename
GladeModelDebugInfotoGladeFormDebugInfoto align with other widgets. -
Rename
GadeModelDebugInfoModaltoGladeFormDebugInfoModal. -
Rename ValidatorResult.
isInvalidtoisNotValidto align with properties in GladeInput and GladeModel. -
Added
setNewInitialValueAsCurrentValuemethod as shorthand for setting new initial value as current input's value. -
Added
GladeDateTimeInput- specialized GladeInput for DateTime inputs. -
Added
inclusiveargument forintvalidations. -
GladeIntInputandGladeDateTimeInputoffer *Nullable versions to support null valuesStringInputdoes not offer a nullable version as we believe that in most cases you don't really need to differentiate between a null string and an empty string. Feel free to open an issue if you disagree.
-
Added Add
isPositive()andisNegative()to Int validator. -
Added Add
validationErrorsgetter as shorthand for getting input's error -
Added Add several extension methods on List of GladeInputError such as
hasErrorKey(). -
Fixed Input did not propagate initialValue into TextEditingController.
-
Fixed Fix nullability value in
devErrorcallback in validator.
3.1.1 #
- Add typedefs
IntInputandBooleanInput - Fix GladeModelDebugInfo colors in DarkMode.
3.1.0 #
- updated dependencies
3.0.1 #
3.0.0 #
Breaking change release
- [Add]: Add
allowBlankparameter toisEmptystring validator. - [Add]: Add
IntInputas a specialized variant of GladeInput - [Add]: Support skipping particular validation with
shouldValidatecallback. - [Breaking]: The
resetToPuremethod on both GladeInput and GladeModel has been renamed tosetAsNewPure. This change better reflects the method's behavior of setting a new pure state rather than resetting to the original state. - [Add]: New
resetToPuremethod added to both GladeInput and GladeModel. This method truly resets the input(s) to their initial value(s) and marks them as pure.
2.3.0 #
- RETRACTED version, should be 3.0.0
2.2.0 #
- [Add]: Add
resetToPureon model level.
2.1.0 #
- [Add]: Add
defaultTranslateErroron model level.
2.0.1 #
- [Fix]: Fix
isUri()to handle URL corectly
2.0.0 #
- [Breaking]: TextEditingController is no more created automatically. When TextEditingController is used, input's behavior is slightly changed. See README.md for full info.
- [Breaking]: GladeInput's controller is now private. Use factory constructors to create input.
- [Breaking]:
Extraparameter removed - [Breaking]:
dependenciesare no longer passed intoonChangeand in validator. - [Breaking]: GladeInput is no longer ChangeNotifier
- [Add]: onDependencyChange - callback is called when any (or multiple with groupEdit()) dependency was udpated.
- Improvement: GladeModelDebugInfo now colorize String values to visualize whitespace.
1.6.0 #
- Improvement: GladeModelDebugInfo is more colorful and polished.
- Improvement: Support deep collection equality when comparing
valueandinitialValue. - [Feat]:
allInputsgetter to support "dynamic" model's inputs validation.
1.5.0 #
- [Feat]: Add
updateWhenNotNullto support shorthand syntax for Widgets with nullable type parameter.
1.4.0 #
- [Feat]: Support non-data-holding inputs to enable "view" inputs.
- [Feat]: Add the
shouldTriggerOnChangeparameter toupdateValueso one can opt-out fromonChangecallback being triggered. - [Fix]: Export
ChangesInfo.
1.3.2 #
- [Fix]:
GladeInputnow preserves selection. (Before, a cursor jumped at the end.)
1.3.1 #
- [Fix]: Fixed
GladeInput.createassert to allow null forvalueandinitialValuewhen input's type is nullable.
1.3.0 #
- [Fix]: When using
GladeInput.create, passing onlyvalueended up in UI vs model not being synced. Now that's fixed. - [Breaking]: StringInput only works with
Stringnow.
1.2.1 #
- [Fix]: Value passed to factory constructor is not reflected in TextController.
1.2.0 #
- [Feat]: Add
GladeFormListenerwidget allowing to listen for model's changes - [Feat]: Add
groupEdit()method in GladeModel allows to update multiple inputs at once.- Works great with
GladeFormListener
- Works great with
- [Feat]: Add
valueTransformin GladeInput. Transform value before it is assigned into value.- Firstly
stringToTypeConverteris called if needed, thenvalueTransform.
- Firstly
- [Feat]: Add
updateValue(T value)as shorthand for inputs when field is not TextField. - [Feat]: Add
resetToPuremethod allowing to reset input into pure state. - [Fix]: Conversion error does not update model's stats and formatted errors.
1.1.2 #
- Fix links in readme
1.1.1 #
- Improve Readme
1.1.0 #
- [Feat]: Add
onChange- support for listening changes and potentially update other inputs based on change
- [Feat]: GladeInput exports TextEditingController now for connecting it with FormField properly
- [Breaking]: StringInput is now alias. Use
GladeInput.stringInputto create string variant
1.0.1 #
- Fix example
1.0.0 #
- Initial version.