forms and the record editor · v1.107.0
JavaScript Form Builder and Record Editor
Lay a form out as fieldsets, rows and columns, validate it, and bind it to a row. The order below is a form on top and its lines in a grid underneath, edited as one record: change the status and a quantity, and one Save writes both.
Try the record editor Free on localhost
a form you can submit
Leave the required fields empty and press Save.
Lay a form out as fieldsets, rows and columns, give each field a control that fits it, and check it all when the user presses Save. The form below is live: submit it empty, then fill it in and submit again.
rows and cols
Rows stack, cols sit side by side.
A form is a tree of rows and cols, each
nesting the other to any depth. A rows block stacks its children top
to bottom. A cols block places them side by side and shares the width
equally unless a child sets its own, and the shell module reads the two words the same way.
Give a child a percentage width and it takes that share of the row, so three items of
33.3% sit on one line. Below a container width you choose, a cols block
stacks into a single column.
what the form gives you
The controls a record needs, and the checks behind them.
Controls
Every control a record needs: text and number inputs, selects and a searchable combo, date, time and date range pickers, colour, rating, chips, a list box, a toggle group, an avatar and a rich-text editor. Each one works from the keyboard, in the four design-system presets and in dark mode. See every control.
Layouts
Fieldsets, rows, cols, spacers and separators. Widths in percent, or in pixels, or flexible. Density levels of compact, standard and comfortable, and a form beside a grid follows that grid’s row height. Columns can wrap, so a row of percentage widths flows onto further lines and each line fills exactly.
Labels where you want them
Labels on the left or on top, at a width you set, or hidden from view while staying the field’s accessible name. Set it for the form, a fieldset or one item. A left label moves to the top when the control would otherwise be squeezed, so a narrow form stays readable.
Number formats and units
A number field shows currency, percent or fixed decimals while it is not focused and stores a plain number. A unit-aware field converts what is typed, so 145 psi into a bar field stores the value in bar, and a temperature scale converts too.
Disabled and read-only
One contract for every control. Disabled leaves the tab order and is skipped by validation. Read-only stays focusable and selectable, refuses every change, and still validates and still appears in the values. Set them per item or for the whole form.
Validation
Required fields, built-in rules for email, number, integer and url, a regular expression, or a function that returns a message. Check on submit, on change or on blur. Failures carry aria-invalid and a message under the field.
Rules that react
visibleWhen, readOnlyWhen and requiredWhen re-run on every committed change, so a field can appear, lock or become required from the value of another.
A stepper for long forms
Give the form a list of steps and it becomes a wizard under a step indicator, horizontal or vertical. Next validates the current step first, Back never does, and the last step reads Finish.
A grid as a field
Put an editable grid inside the form and its rows become the field’s value. Required cells and column rules are checked with the rest of the form, and the message names the row and the column.
Bound to a grid or the data router
Bind a form to a grid row and it builds one item per column when you declare no layout, tracks which items are dirty, and saves through the grid’s own edit path. Bind it to a data router record and it follows the feed without overwriting what a user is typing.
Files and combos
A file drop area accepts drop, paste or pick, enforces type, size and count, and shows progress with retry and remove. A combo pages and searches a server list, takes avatars, icons and dots on its options, and can allow new entries.
Every framework, and htmx
Wrappers for React, Vue, Svelte and Angular. On an htmx page, a server-rendered form is enhanced in place with a data attribute, keeping its field names and its posts, with validation before the post goes out.
Every control
| Control | What it does |
|---|---|
| Text inputs | Text, email, password, url, number and textarea fields. |
| Choices | Checkbox, toggle with on and off text, select, radio and checkbox groups, and chips. |
| Searchable combo | A select you can type into, for long option lists. |
| Date and time | Date, date-time and time pickers; the time field has 12 or 24 hour display and typed entry. |
| Date range | A start and an end in one field, two months side by side, presets such as last 7 days, limits and a month-range mode. |
| List box | An always-visible option list with single, multiple or checkbox selection, a filter box, groups and reordering, and two connected lists that pass items between them. |
| Toggle group | A row of two-state buttons, one per option, exclusive or independent. |
| Colour | A swatch with its hex value and a palette of preset shades, remembered custom colours and typed hex entry. |
| Rating and stage pipeline | Stars for a score, and a pipeline for a record's stage. |
| Avatar | A profile picture picked by click, keyboard or drag and drop, with a fallback and an optional upload. |
| Rich text | A sanitised rich-text editor. |
| One-time code | Entry for a verification code, one box per character. |
| Buttons and speed dial | Buttons, and a floating action button that opens its actions in a strip or a fan. |
| Content container | Your own HTML, or another view, placed inside the form. |
a form from a config
Describe the fields, get the form.
Drop in one script tag, then hand createForm your rows. Read the
values with getValue(), write them with
setValue(), and listen for change or
submit.
<!-- the form module, as a global -->
<script src="https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/form.min.js"></script>
<script>
var form = LatticeGridForm.createForm(document.querySelector('#deal'), {
rows: [
{ fieldset: 'Opportunity', cols: [ // cols sit side by side
{ type: 'input', name: 'name', label: 'Name', required: true, width: '33.3%' },
{ type: 'input', name: 'account', label: 'Account', required: true, width: '33.3%' },
{ type: 'combo', name: 'owner', label: 'Owner', options: people, width: '33.3%' }
] },
{ type: 'number', name: 'amount', label: 'Amount',
format: { style: 'currency', currency: 'USD' }, min: 0 },
{ type: 'buttons', align: 'end', items: [
{ name: 'save', label: 'Save', variant: 'primary', buttonType: 'submit' }
] }
]
});
// A submit button validates first, then fires submit with the values.
form.el.addEventListener('submit', function (e) { save(e.detail.values); });
</script>
form groups
Several forms, one record.
Put a form in each cell of a layout and join them with createFormGroup.
The group reads, writes, validates and locks as one form, and binds to a
data router record and saves back through it.
var header = LatticeGridForm.createForm(headerCell, { rows: [
{ type: 'input', name: 'name', label: 'Name', value: 'Ada' },
{ type: 'input', name: 'plan', label: 'Plan', value: 'team' }
] });
var details = LatticeGridForm.createForm(detailsCell, { rows: [
{ type: 'input', name: 'email', label: 'Email', value: 'ada@example.com' },
// This rule watches a field the header form owns.
{ type: 'input', name: 'coupon', label: 'Coupon',
visibleWhen: { name: 'plan', equals: 'enterprise' } }
] });
var group = LatticeGridForm.createFormGroup([header, details]);
group.getValue(); // both forms, merged
group.setValue({ email: 'grace@example.com' }); // routed to the details form
group.validate(); // one answer for every form
docs
Reference and the rest of the product.
Form API
Every control, option and method.
Editable cells with validation
The same rules on grid cells.
Record editor
A form and its related rows, saved once.
Application layout
Panels, tabs, drawers and dialogs.
Data router
Drive a form from one live feed.
All modules
Each module and its size.
Also in the licence
- GridThe data grid with derived grids, statistics and Explain built in.
- DashboardsKPI tiles, charts and the Designer, on the same rows.
- GanttDependencies, critical path and resource load.
- KanbanA board over the rows you already have.
- CalendarA schedule view over a date column.
- SchedulerPeople and machines allocated to work.