valiform 1.1.0
valiform: ^1.1.0 copied to clipboard
A Flutter form validation library built on Validart. Provides reactive state management, typed fields, and seamless Form widget integration.
Changelog #
1.1.0 - 2026-04-22 #
Added #
- Async validation — first-class support for validart 1.1.0 async primitives (
refineAsync,preprocessAsync,transformAsync).VForm.validateAsync()— runs the full async pipeline and surfaces errors through the normalFormFielderror channel (via persistent imperative errors), so the UI updates exactly like sync validation.VForm.silentValidateAsync()— async validation without touching the UI.VForm.errorsAsync()/VForm.vErrorsAsync()— async counterparts for inspecting current errors.VForm.valueAsync— awaits each field's async pipeline and returns the fully-parsed value.VForm.hasAsync/VField.hasAsync— introspection flag for schemas that require async validation.VField.validateAsync(),VField.errorAsync,VField.vErrorAsync,VField.parsedValueAsync— per-field async APIs with the same semantics as their sync siblings.- Conditional
.when()rules now detect async schemas and register them into the async validation path automatically.
- Async example page —
example/lib/pages/async_validation_page.dartdemonstrates a simulated remote username-availability check with loading state. - Schema
defaultValuenow seeds the VField initial value — when.form()isn't given an explicit value for a field, the schema'sdefaultValue(if any) auto-populates the UI and is the target ofreset(). Resolution order:initialValues[key](even an explicitnull) →schema.defaultValue→null. Reinforces the semantic that a field withdefaultValueis never required — validart substitutes the default for null before any validator runs. Required Messageexample page —example/lib/pages/required_message_page.dartcomparesV.bool(message: ...)againstpreprocess((v) => v ?? false)as two ways to customize the error on an untouched checkbox.Default Valueexample page —example/lib/pages/default_value_page.dartdemonstrates the three combinations (defaultValueonly,initialValuesonly, both) side by side with their respectivereset()andrequiredsemantics.VField.initialValuegetter — exposes the stable initial value resolved at form construction (initialValues[key]→schema.defaultValue→null). Prefer binding widgets'initialValueparameter to this getter instead ofVField.valuesoFormField.reset()always targets the true starting point, even when the widget tree rebuilds during typing.
Changed #
- Synchronous inspection methods now mirror validart's strict contract: when the schema contains any async step,
VForm.validate,silentValidate,errors,vErrors,value,VField.validate,error,vError, andparsedValuethrowVAsyncRequiredException. Use the corresponding*Asyncvariants.VField.validator(T?)is the single sync adapter kept tolerant — it is required by Flutter's synchronousFormField.validatorsignature and is the channelvalidateAsyncuses to surface async errors viasetError(persist: true). - Bumped minimum validart constraint to
1.1.0forVType.isNullable,VType.hasAsync,VType.hasDefault,VType.defaultValueOrNull, and the async pipeline APIs.
Fixed #
VField.parsedValue/parsedValueAsyncnow normalize empty strings tonullbefore callingsafeParse, so a schema'sdefaultValueis applied consistently when the user clears a text field. PreviouslyparsedValuereturned the raw empty string, causingform.valueto disagree withform.validate()in defaulted schemas.
1.0.0 - 2026-04-18 #
Breaking Changes #
- Removed validart re-export — import
package:validart/validart.dartseparately. - Removed built-in
TextEditingController— useattachTextController()for bidirectional sync. VFormis now generic —VForm<Map<String, dynamic>>for VMap,VForm<T>for VObject.- Replaced
Validart()instance — use theVclass (V.string(),V.map(), ...). - Replaced
.refine(check, path:)— use.refineFormField(check, path:). - Removed
VNumsupport — useVIntorVDoubledirectly. - Renamed
defaultValues→initialValuesonVMap.form()/VForm.map(). - Renamed
defaultValue→initialValueonVObject.form()/VForm.object(). VField.onChangednow acceptsT?— compatible with widgets likeDropdownButtonFormFieldwhoseonChangedpasses a nullable value.VField.validate()now runs all validators without side-effects — previously only ran the schema check. Behaviour of the Flutter-facingvalidator(value)is unchanged.
Added #
- VObject support —
V.object<T>().form(builder:)returns typedTinstead ofMap. - Typed fields via
mapType—VField<Country>,VField<DateTime>, and any custom type are preserved across the schema pipeline (no moreVField<dynamic>fallback). - Conditional validation (
.when()) — schema rules are plumbed into per-field validators automatically. - Nullable fields — empty strings are normalized to
nullfor.nullable()types. initialValues/initialValue— seed values at form construction, forVMapandVObjectforms respectively.parsedValuegetter onVField— value after pipeline transforms (trim,toLowerCase, ...).rawValueonVForm— untransformed field values asMap<String, dynamic>.onValueChangedon form factory plusaddValueChangedListener/removeValueChangedListeneronVFormfor dynamic subscription.attachController(ValueNotifier<T?>, {owns = true})— bidirectional sync with any custom controller that extendsValueNotifier<T?>(e.g.LuneSelectFieldController<T>). Owned by default — the controller is disposed together with the field. Passowns: falseto keep external lifecycle management.attachTextController(TextEditingController, {owns = true})— extension onVField<String>for text inputs (sinceTextEditingController.valueisTextEditingValue, notString).controller/textControllergetters — typed access to the currently attached controller.detachController()— remove sync listeners without disposing the controller.onValueChanged(callback)onVField— bridge for external state that isn't aValueNotifier. Registers a typed callback on every value change and returns a dispose function.- Imperative error setting —
VField.setError(message, {persist, force})/clearError()and theVFormcounterparts (setError,setErrors,clearError,clearErrors). Useful for backend rejections, async checks, and external-state business rules.- Default (one-shot) — the error surfaces on the next
validator()call and is cleared on it, even when a standard validator wins the precedence. Prevents "ghost" errors on later valid input. persist: true— keeps the error across validations untilclearError()is called explicitly.force: true— overrides standard-validator precedence so the manual error shows even on fields that would fail their own rules.persist: true, force: true— always shown until cleared (server-side blocks like "Account suspended").
- Default (one-shot) — the error surfaces on the next
VField.key— optionalGlobalKey<FormFieldState<T>>that, when attached to aFormField, letssetErrorrevalidate only that field (other fields are untouched).VForm.errors()/VField.error— read-only inspection of current validation state (all fields or single field). Does NOT consume one-shot manual errors, does NOT touch the UI. Perfect for live error summary panels and debug tooling.VForm.vErrors()/VField.vError— likeerrors()/errorbut return the fullList<VError>(preservingcode,path,message). Useful for array fields wherepathcontains the failing element's index, or when you need the validator code for custom UI.
Changed #
form.valuereturns parsed values (transforms applied).form.silentValidate()now mirrorsvalidate()semantically — runs per-field validators AND the schema validator, consuming one-shot manual errors — while still not touching the UI.- Controller sync uses equality checks and a
_syncingguard to avoid cascading updates.
Fixed #
- Re-attaching the same owned controller no longer disposes it —
attachControllerandattachTextControlleruse an identity check before disposing the previously owned instance, sofield.attachController(ctrl); field.attachController(ctrl);is safe.
0.0.3 - 2025-02-27 #
0.0.2 - 2025-02-27 #
0.0.1 - 2025-02-25 #
- Initial release