rj_form_engine 1.0.1
rj_form_engine: ^1.0.1 copied to clipboard
Schema-driven dynamic form engine for Flutter with validation, rich field types, and minimal dependencies.
1.0.1 #
Searchable dropdown field — filter-as-you-type dropdown with custom overlay positioning.
Added #
FieldType.searchableDropdown— new field type for searchable/filterable dropdownsFieldMeta.searchableDropdown()— typed factory constructor for the new field typeSearchableDropdownConfig— typed config class supportinghintText,maxHeight,offsetY,offsetXfor overlay customizationRjSearchableDropdownField— widget that renders aTextFormFieldwith an overlay list that filters items as the user typesFieldMeta.searchableDropdownConfigaccessor — fallback to defaults when no config providedFieldType.searchableDropdowncase inrj_form.dartswitch, wired with label shadowing (same as regular dropdown)
FieldMeta.searchableDropdown(
key: 'country',
label: 'Country',
required: true,
dropdownSource: DropdownSource.async(fetchCountries),
config: const SearchableDropdownConfig(
hintText: 'Search country...',
maxHeight: 300,
),
)
1.0.0 #
Stable release — typed factory constructors, responsive grid layout, enhanced DX, and zero breaking changes.
Added #
Typed Factory Constructors
- 13 factory constructors on
FieldMeta:.text(),.number(),.textArea(),.date(),.dropdown(),.image(),.slider(),.spinner(),.timePicker(),.toggle(),.radio(),.chip(),.custom() - Each factory surfaces only the params relevant to that field type — no more
spinnerMinon a text field FieldMeta.custom()enhanced — now acceptshint,derivation,showLabel,labelConfig- Old
FieldMeta(key: ..., type: ..., ...)constructor is unchanged — zero breaking changes
// Before
FieldMeta(key: 'email', label: 'Email', type: FieldType.text, required: true)
// After
FieldMeta.text(key: 'email', label: 'Email', required: true)
Responsive Grid Layout
RjSpanenum —full,half,third,quarterfor declaring field widthsRjLayoutclass — configurable per-field layout withmd(tablet) and optionallg(desktop)- Row-packing grid engine — consecutive fields auto-group into
IntrinsicHeightrows based on their span - Mobile-first — phone (below 768px) always stacks full-width automatically; no config needed
- Section-aware — sections flush the current row and start fresh
RjResponsive.resolveSpan()— resolves the effective column count from layout + screen widthRjLayout? layoutproperty on all factory constructors andcopyWith
FieldMeta.text(
key: 'email',
label: 'Email',
required: true,
layout: const RjLayout(md: RjSpan.half), // side-by-side on tablet+
)
Other
hintparameter added toFieldMeta.radio()andFieldMeta.chip()factories
Changed #
- Version bumped to 1.0.0 — stable API surface with all core features production-ready
Documentation #
- README fully rewritten: all examples use typed factory constructors
- New "Responsive Grid" section with
RjSpan/RjLayoutAPI docs - Updated Limitations — multi-column grid is now natively supported
- Updated Roadmap — grid layout and typed factories marked complete
0.3.0 #
Auto-derivation release — computed fields, label shadowing, chained derivations, and label customization.
Added #
FieldDerivationclass — declare that a field's value is auto-computed from other fields via a purecomputefunctionFieldMeta.derivationproperty — attach a derivation to any field typeFormController.setValueWithDerivation()— updates a value and recalculates all affected derived fieldsFormController.setValueAndClearDependents()— now acceptsextraValuesfor label shadowing (e.g.,{'groupIdLabel': 'Dairy Cows'})FormController.recomputeAllDerivations()— recalculates all derived fields aftersetAll()(for edit mode)- Label shadowing — dropdown labels are automatically stored alongside IDs (e.g.,
groupId+groupIdLabel) socomputefunctions have synchronous access to human-readable text - Chained derivations — if field A derives B and B derives C, changing A updates the entire chain in one pass
- Derived fields are automatically read-only (
AbsorbPointer) — users cannot manually edit computed values - Derived field errors are automatically cleared when a source field changes
RjDropdownField.onChangednow passes the selected item's label alongside the ID
Examples #
// Simple: default_value × 2 → derived_from_default
FieldMeta(
key: 'derived_from_default',
label: 'Doubled Value',
type: FieldType.number,
derivation: FieldDerivation(
derivesFrom: ['default_value'],
compute: (state) {
final val = (state['default_value'] as num?)?.toDouble();
return val != null ? val * 2 : null;
},
),
)
// Multi-source: price × quantity → total
FieldDerivation(
derivesFrom: ['price', 'quantity'],
compute: (state) {
final price = (state['price'] as num?)?.toDouble() ?? 0;
final qty = (state['quantity'] as num?)?.toDouble() ?? 0;
return price * qty;
},
)
// Label shadowing: combine dropdown labels into a tag
FieldDerivation(
derivesFrom: ['category', 'item'],
compute: (state) {
final cat = state['categoryLabel'] ?? '';
final item = state['itemLabel'] ?? '';
return [cat, item].where((p) => p.isNotEmpty).join(' - ');
})
Added (Label Customization) #
RjLabelsealed class — customize field labels withRjLabelText(styled text) orRjLabelCustom(any widget)FieldMeta.showLabel(defaulttrue) — set tofalseto hide the field label entirelyFieldMeta.labelConfig— when set withshowLabel: true, overrides the default label with a customRjLabelwidget rendered above the fieldRjFormTheme.inputDecoration()—labelparameter is now nullable, allowing label suppression at the decoration level
Examples #
// Hide the label entirely
FieldMeta(
key: 'no_label',
label: 'Hidden Label',
type: FieldType.text,
showLabel: false,
)
// Styled text label
FieldMeta(
key: 'styled',
label: 'Default',
type: FieldType.text,
labelConfig: const RjLabelText(
text: 'Bold Blue Label',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.blue),
),
)
// Custom widget label
FieldMeta(
key: 'custom',
label: 'Default',
type: FieldType.number,
labelConfig: RjLabelCustom((context) => Row(
children: [Icon(Icons.star), Text('Custom Label')],
)),
)
0.2.1 #
- Added toggle obscure functionality to show/hide text in password fields.
0.2.0 #
Refactor release — improved API consistency, performance, and type safety.
Added #
- Typed
FieldConfigsubclasses:SliderConfig,SpinnerConfig,ImageConfig,DateConfig,TextConfig,TimeConfig FieldMeta.configproperty for typed field configuration (takes precedence over flat params)- Typed config accessors on
FieldMeta:sliderConfig,spinnerConfig,imageConfig,dateConfig,textConfig,timeConfig errorsSummaryBuildercallback onRjFormfor custom error summary messagesonSuccesscallback onRjForm— fires afteronSubmitcompletes successfullyautoClearOnSubmitoption onRjFormto automatically reset form after submissionautoDismissKeyboardoption onRjForm(default:true)FieldMeta.copyWith()method for creating modified field copiesSemanticslabels on all field widgets for improved accessibilityRjTimeUtilsutility class for custom date/time formatting
Changed #
CustomFieldBuildersignature now includes the fullFieldMetaas the second parameterDropdownSource.asyncloader now receivesparentValueas a named parameter:({String? parentValue})FieldMeta.sectionfactory now requires an explicitkeyparameter to prevent key collisions- Per-field rebuild optimization —
_FieldBuilderonly rebuilds when its own value, error, or parent value changes - Dropdown "waiting for parent" state now uses
AbsorbPointer+Opacityinstead of deprecatedinitialValue RjFormThemeuseswithValues(alpha:)instead of deprecatedwithOpacity()
Fixed #
- Section key collision when multiple sections share the same label
- Improved Dropdown handling to align with controlled form patterns
TextEditingControllermemory leak inRjTimePickerField- Dropdown assertion crash when pre-filled value is not in the loaded items list
- Form state sync when
FieldMetachanges at runtime viadidUpdateWidget
Breaking Changes #
CustomFieldBuildersignature changed: addedFieldMeta fieldas the second parameter. Update custom field builders from(context, value, onChanged, errorText)to(context, field, value, onChanged, errorText).FieldMeta.sectionnow requires an explicitkeyparameter. Previously auto-generated keys from labels could collide.DropdownSource.asyncloader signature changed:parentValueis now a named parameter. Update from(parentValue) async => ...to({parentValue}) async => ....
0.1.0 #
Initial public release.
Added #
- 13 field types:
text,number,date,dropdown,textArea,image,slider,timePicker,spinner,toggle,radio,chip,custom FieldMetaschema-driven field definition with 20+ configuration optionsRjFormwidget — renders fields from aList<FieldMeta>schemaFormController(ChangeNotifier) for external form state managementDropdownSourceunion type — static or async dropdown item loading- Cascading dropdowns with auto-reload and auto-clear on parent change
FieldDependencyfor conditional field visibility with custom condition predicates- 25+ built-in validators via
RjValidators: email, phone, URL, password rules, date ranges, length bounds, regex patterns, and more RjFormThemefor full visual customization of all field styles- Pre-fill support via
initialValuesfor edit and clone modes - View-only (read-only) mode via
viewOnlyflag onChangedcallback for real-time field change tracking- Error summary display at the top of the form (
showErrorsSummary) - Custom date/time format strings (
dateFormat,timeFormat) FieldMeta.customfor embedding any custom widget via a builder functionFieldMeta.sectionfor visual form section dividers- Keyboard dismissal via tap outside fields
- Minimal dependencies: only
flutterSDK +image_picker - State-management agnostic — works with Provider, Riverpod, Bloc, GetX, or nothing