Intro
First lets take a look at whats possible with informed. Below is an example where we wrapped informed around Adobe's desgin-system.
Those components got defined once inside `YourComponents` directory. You will see how this was done later inside the setup docs.
Example:
Code:
// Example.jsx
import { Relevant, Debug } from 'informed';
// Inputs that were hooked up to informed via "useField"
import { Form, Input, Select, Checkbox, Option, Button } from 'YourComponents';
const onSubmit = ({ values }) => window.alert(`Hello ${values.name}`);
const Example = () => (
<Form onSubmit={onSubmit} initialValues={{ phone: '1234567899' }}>
<Input name="name" label="Name" placeholder="Elon" required />
<Input name="age" type="number" label="Age" required="Age Required" />
<Input name="phone" label="Phone" formatter="+1 (###)-###-####" />
<Select name="car" label="Car" initialValue="ms">
<Option key="ms">Model S</Option>
<Option key="m3">Model 3</Option>
<Option key="mx">Model X</Option>
<Option key="my">Model Y</Option>
</Select>
<Checkbox name="married" label="Married?" />
<Relevant when={({ formState }) => formState.values.married}>
<Input name="spouse" label="Spouse" />
</Relevant>
<Button type="submit">Submit</Button>
<Debug valid pristine dirty values errors />
</Form>
);
export default Example;
Whats going on here? Basically informed manages form state for you, and allows you to easily hook ito its state managemenet with the use of
Above, we imported inputs that were already wrapped and simply rendered them on the page.
This is the way! You should most of the time not even realize you are using a form library 😁
useField
Above, we imported inputs that were already wrapped and simply rendered them on the page.
This is the way! You should most of the time not even realize you are using a form library 😁
Capabilities
Informed is cabable of A LOT of cool things! The below example shows off many of those cababilites in one form.
- Arrays: ability to render dynamic arrays of fields
[ 'a', 'b' ]
or[ { name: 'Joe', age: 29 }, { name: 'Hope', age: 24 }]
- Relevance: ability to render fields conditionally depending on the state of other parts of the form
- JSPAN: ability to easily and intuitively manipulate form state
- Formatting: ability to perform display formatting, where the format shown to user can differ from the state of the values stored
- Validation: ability to perform both synchronous and asynchronous validation in a controlled manner
- Api: ability to manipulate the form state both inside and outside the context of the form
- State: ability to access field and form data
- Multistep: ability to create dynamic multistep forms
- Scope: ability to scope ( group ) fields
- Schema: ability to render forms based on pure JSON schema
- Dynaic: ability to hide and show fields ( render and unrender ) and either cleanup or maintain state of unmounted fields
- Debugging: ability to easily debug users state as well as internals of the library
- Nesting: ability to have highly nested value structure
state.values.friends[1].brother.parents.cars[0].model
Example:
Code:
// Example.jsx
import {
Debug,
Relevant,
ArrayField,
Scope,
FormFields,
utils
} from 'informed';
import { Form, Input, Select, Checkbox, Option, Button } from 'YourComponents';
/* ----------------- On Submit Gets Entire Form State ------------------ */
const onSubmit = ({ values }) => window.alert(`Hello ${values.name}`);
/* ------------------- Custom Field Level Validation ------------------- */
const validatePassword = (value, { password1, password2 }) => {
if (password1 !== password2) return 'Passwords must match';
};
/* ----------------------- Intl Number Formatter ----------------------- */
const { formatter, parser } = utils.createIntlNumberFormatter('en-US', {
style: 'currency',
currency: 'USD'
});
const Example = () => (
/* -------------------- Form Level initialValues --------------------- */
<Form
onSubmit={onSubmit}
initialValues={{ phone: '1234567899', salary: 80_000.25 }}>
{/* ------------------ Built in validation props ------------------- */}
<Input name="name" label="Name" required />
{/* --------------- Override default error messages ---------------- */}
<Input name="age" type="number" label="Age" required="Age Required" />
{/* ----------------------- Format inputs -------------------------- */}
<Input name="phone" label="Phone" formatter="+1 (###)-###-####" />
<Input name="salary" label="Salary" formatter={formatter} parser={parser} />
{/* --------------------- Paried Validation ------------------------ */}
<Input
name="password1"
label="Password"
required
minLength={8}
validate={validatePassword}
validateOn="change"
showErrorIfError
validateWhen={['password2']}
/>
<Input
name="password2"
label="Confirm password"
required
minLength={8}
validate={validatePassword}
validateOn="change"
showErrorIfError
validateWhen={['password1']}
/>
{/* ------------------ Field Level default value ------------------- */}
<Checkbox name="love" label="Do you love Tesla?" defaultValue={true} />
{/* ------------------- Field Level initial value ------------------- */}
<Select name="car" label="Car" initialValue="ms">
<Option key="ms">Model S</Option>
<Option key="m3">Model 3</Option>
<Option key="mx">Model X</Option>
<Option key="my">Model Y</Option>
</Select>
{/* --------------------------- Relevance --------------------------- */}
<Checkbox name="married" label="Are you Married?" />
<Relevant when={({ formState }) => formState.values.married}>
<Input name="spouse" label="Spouse" required />
</Relevant>
{/* ---------------------------- Scope ------------------------------ */}
<Scope scope="mother">
<Input name="name" label="First name:" initialValue="Maye" />
<Input name="name" label="Last name:" initialValue="Musk" />
<Input name="age" label="Age:" type="number" initialValue={74} />
</Scope>
{/* ------------------------- Array Fields -------------------------- */}
<br />
<h3>Children</h3>
<ArrayField
name="children"
initialValue={[
{
name: 'Jake',
age: '18'
},
{
name: 'Joy',
age: '15'
}
]}>
{({ add }) => (
<>
<Button onClick={add} type="button" variant="accent" style="outline">
Add
</Button>
<ArrayField.Items>
{({ remove, name }) => (
<>
<Input name="name" label="Name" required />
<Input name="age" label="Age" type="number" />
{/* ----------------- Scoped Relevance ------------------ */}
<Relevant
when={({ formApi, scope }) =>
formApi.getValue(`${scope}.age`) >= 16
}>
<Select name="car" label="What car do they drive?">
<Option key="ms">Model S</Option>
<Option key="m3">Model 3</Option>
<Option key="mx">Model X</Option>
<Option key="my">Model Y</Option>
</Select>
</Relevant>
<Button type="button" onClick={remove} variant="negative">
Remove
</Button>
</>
)}
</ArrayField.Items>
</>
)}
</ArrayField>
<br />
{/* ------------------------- Table Forms -------------------------- */}
<table className="form-table">
<thead>
<tr>
<th>Market</th>
<th>Supply</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
{/* --------------- Scope using Scope --------------- */}
<Scope scope="US">
<td>US</td>
<td>
<Input name="supply" type="number" initialValue={100} />
</td>
<td>
<Input name="price" type="number" initialValue={40_000} />
</td>
</Scope>
</tr>
{/* ------------- Scope using path syntax ------------- */}
<tr>
<td>CA</td>
<td>
<Input name="CA.supply" type="number" initialValue={50} />
</td>
<td>
<Input name="CA.price" type="number" initialValue={42_000} />
</td>
</tr>
</tbody>
</table>
{/* ------------------- JSON Schema Rendering -------------------- */}
<FormFields
schema={{
type: 'object',
properties: {
bio: {
type: 'string',
title: 'Bio',
'ui:control': 'textarea'
},
birthday: {
type: 'text',
title: 'Birthday',
'ui:control': 'input',
'ui:props': {
type: 'date'
}
}
}
}}
/>
{/* ------- Automaically calls onSubmit for submit button ---------- */}
<Button type="submit" variant="accent" style="fill">
Submit
</Button>
{/* ----------------------- Debug Component ------------------------- */}
<Debug />
</Form>
);
export default Example;
How do I start!?
In order to use informed all you need to do is wrap your own inputs with informed via a `useField` hook.
You do this one time and then can use your form inputs as normal JSX or via schema! Lets go get SETUP