Question types overview
Forms-Engine ships twelve question types. Each owns four things: what it renders in the embed, its configuration options in the editor, the shape its answer is stored in, and the rule operators conditions may use against it.
| Type | Renders | Stored answer | Rule operators |
|---|---|---|---|
| Text box | single/multi-line text input | string | equals, not equals |
| Radio | radio group | string (option label) | equals, not equals |
| Checkboxes | checkbox group | array of option labels | contains, does not contain |
| Dropdown | searchable select | string (option label) | equals, not equals |
| Date | text input + popup calendar | "YYYY-MM-DD" string |
equals, not equals, before, after |
| Number | numeric input, optional %/currency adornment | JSON number | equals, not equals, greater than, less than |
| email input | string | equals, not equals | |
| Phone | phone input | string | equals, not equals |
| Toggle | two-button yes/no control | boolean | equals, not equals |
| Address | multi-field address with geocoding autocomplete | flat object of sub-fields | equals, not equals (per sub-field) |
| File upload | drag-and-drop dropzone | array of file references | — |
| Display text | sanitized rich text, no input | — (never stored) | — |
Three cross-cutting facts worth knowing before the per-type pages:
- Answers are typed.
0is a real number answer andfalsea real toggle answer — “answered” never means “truthy”. An empty text box or an empty checkbox selection stores nothing at all (the key is removed, never an empty string or empty array). - Choice answers store the option label, so responses read naturally in Mongo and CSV without a lookup table. Option ids exist in the definition for future-proofing, not in the stored data.
- Unknown types degrade gracefully. A definition containing a type the
embed doesn’t know (e.g. from a newer server) renders a neutral
placeholder, never blocks navigation, and reports itself via
fe-error— old embeds don’t break when new types ship.
Question types are also the extension point: adding one requires only new
registry modules (core semantics, renderer template, editor panel, backend
validator) with zero changes to navigation, persistence, or the rule
engine. The worked example lives in the repo at
docs/adding-a-question-type.md.