Advanced Patterns
Conditional rendering, dynamic forms, and advanced techniques.
Conditional Rendering with IfFormValues
Show or hide content based on form values:
import { Form, Field, IfFormValues } from 'efx-forms';
function Input({ id, label, value, error, ...props }) {
return (
<div>
<label htmlFor={id}>{label}</label>
<input id={id} value={value || ''} {...props} />
{error && <span className="error">{error}</span>}
</div>
);
}
function ConditionalForm() {
return (
<Form name="conditional-form" onSubmit={(values) => console.log(values)}>
<Field name="age" Field={Input} label="Age" type="number" />
{/* Show when age >= 18 */}
<IfFormValues check={({ age }) => age >= 18}>
<div className="adult-content">
<Field name="license" Field={Input} label="Driver's License Number" />
</div>
</IfFormValues>
<button type="submit">Submit</button>
</Form>
);
}
Auto-Fill with setTo
Automatically set field values when condition becomes true:
import { Form, Field, IfFormValues } from 'efx-forms';
function AutoFillForm() {
return (
<Form name="autofill-form" onSubmit={(values) => console.log(values)}>
<Field name="subscribe" Field={Checkbox} label="Subscribe to newsletter" />
<IfFormValues
check={({ subscribe }) => subscribe}
setTo={{ email: 'subscribe@example.com' }}
>
<Field name="email" Field={Input} label="Email" type="email" />
</IfFormValues>
<button type="submit">Submit</button>
</Form>
);
}
Clear Values with resetTo
Reset field values when condition becomes false:
import { Form, Field, IfFormValues } from 'efx-forms';
function ResetOnHideForm() {
return (
<Form name="reset-form" onSubmit={(values) => console.log(values)}>
<Field name="showExtra" Field={Checkbox} label="Show extra field" />
<IfFormValues
check={({ showExtra }) => showExtra}
resetTo={{ extra: '' }}
>
<Field name="extra" Field={Input} label="Extra Field" />
</IfFormValues>
<button type="submit">Submit</button>
</Form>
);
}
Conditional Rendering with IfFieldValue
Simpler conditional based on single field value:
import { Form, Field, IfFieldValue } from 'efx-forms';
function StatusForm() {
return (
<Form name="status-form" onSubmit={(values) => console.log(values)}>
<Field name="status" Field={Input} label="Status" />
<IfFieldValue
field="status"
check={(value) => value === 'active'}
>
<div className="status-message">Status is active</div>
</IfFieldValue>
<button type="submit">Submit</button>
</Form>
);
}
Render Prop Pattern
Custom rendering with field value:
import { Form, Field, IfFieldValue } from 'efx-forms';
function RenderPropForm() {
return (
<Form name="render-form" onSubmit={(values) => console.log(values)}>
<Field name="status" Field={Input} label="Status" />
<IfFieldValue
field="status"
check={(value) => value === 'active'}
render={(value) => <div>Current status: {value}</div>}
/>
<button type="submit">Submit</button>
</Form>
);
}
Nested Conditionals
Combine multiple conditional components:
import { Form, Field, IfFormValues, IfFieldValue } from 'efx-forms';
function NestedConditionalForm() {
return (
<Form name="nested-form" onSubmit={(values) => console.log(values)}>
<Field name="enabled" Field={Checkbox} label="Enable feature" />
<Field name="level" Field={Input} label="Level" type="number" />
<IfFieldValue
field="enabled"
check={(enabled) => enabled}
>
<IfFormValues check={({ level }) => level > 10}>
<div className="high-level">
<Field name="highLevelField" Field={Input} label="High Level Field" />
</div>
</IfFormValues>
</IfFieldValue>
<button type="submit">Submit</button>
</Form>
);
}
Dynamic Fields
Render fields dynamically based on form state:
import { Form, Field, FormDataProvider } from 'efx-forms';
function DynamicFieldsForm() {
const fieldCount = 3;
return (
<Form name="dynamic-form" onSubmit={(values) => console.log(values)}>
<FormDataProvider>
{({ values }) => (
<>
<Field name="count" Field={Input} label="Number of fields" type="number" />
{Array.from({ length: values.count || fieldCount }).map((_, idx) => (
<Field
key={idx}
name={`dynamic[${idx}]`}
Field={Input}
label={`Dynamic Field ${idx + 1}`}
/>
))}
</>
)}
</FormDataProvider>
<button type="submit">Submit</button>
</Form>
);
}
Using Form Hooks Outside Form Context
Access form data and methods programmatically (must provide form name when outside Form):
import { Form, Field, useFormValues, useFormMethods } from 'efx-forms';
function FormWithExternalControl() {
// Must provide formName when used outside Form context
const values = useFormValues('external-control-form');
const { reset, setValues } = useFormMethods('external-control-form');
return (
<div>
<Form name="external-control-form" onSubmit={(values) => console.log(values)}>
<Field name="name" Field={Input} label="Name" />
<Field name="email" Field={Input} label="Email" type="email" />
<button type="submit">Submit</button>
</Form>
{/* External controls - outside Form context */}
<div className="controls">
<button onClick={reset}>Reset Form</button>
<button onClick={() => setValues({ name: 'John', email: 'john@example.com' })}>
Fill Form
</button>
<pre>Current values: {JSON.stringify(values, null, 2)}</pre>
</div>
</div>
);
}
Using getForm Outside Component Tree
Access form instance from anywhere:
import { Form, Field, getForm } from 'efx-forms';
// Get form instance by name
const form = getForm({ name: 'my-form' });
// Access form stores
form.$values.watch((values) => {
console.log('Form values changed:', values);
});
// Call form methods
form.reset();
form.setValues({ name: 'John' });
function ExternalFormAccess() {
return (
<Form name="my-form" onSubmit={(values) => console.log(values)}>
<Field name="name" Field={Input} label="Name" />
<button type="submit">Submit</button>
</Form>
);
}
Debounced Updates
Debounce conditional rendering updates:
import { Form, Field, IfFormValues } from 'efx-forms';
function DebouncedForm() {
return (
<Form name="debounced-form" onSubmit={(values) => console.log(values)}>
<Field name="search" Field={Input} label="Search" />
<IfFormValues
check={({ search }) => search.length > 2}
updateDebounce={300} // Wait 300ms after typing stops
>
<div className="search-results">
Search results for: {values.search}
</div>
</IfFormValues>
<button type="submit">Submit</button>
</Form>
);
}
Form Data Provider Patterns
Subscribe to form data changes:
import { Form, Field, FormDataProvider, FieldDataProvider } from 'efx-forms';
function DataProviderForm() {
return (
<Form name="provider-form" onSubmit={(values) => console.log(values)}>
<Field name="username" Field={Input} label="Username" />
<Field name="email" Field={Input} label="Email" type="email" />
{/* Subscribe to all form data */}
<FormDataProvider>
{({ values, errors, touched, dirty }) => (
<div className="form-debug">
<h4>Form State</h4>
<p>Dirty: {dirty ? 'Yes' : 'No'}</p>
<p>Touched: {touched ? 'Yes' : 'No'}</p>
<p>Errors: {Object.keys(errors).length}</p>
<pre>{JSON.stringify(values, null, 2)}</pre>
</div>
)}
</FormDataProvider>
{/* Subscribe to single field */}
<FieldDataProvider name="username">
{({ value, active }) => (
<div>
Username: {value} (Active: {active ? 'Yes' : 'No'})
</div>
)}
</FieldDataProvider>
<button type="submit">Submit</button>
</Form>
);
}
Next Steps
- Check the API Reference for complete component documentation
- Review the Examples page for more patterns