Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / Web app

Reference

Generic form

Reference for gen-form.js, customselect.js, and form-drafts.js, which build create and edit forms and read-only record cards from FormMeta.

webapp/js/gen-form.js builds every create form, edit form, action form, and read-only record card of the web app from EntityMeta.form. webapp/js/form-drafts.js keeps unsaved input during a session, and webapp/js/customselect.js restyles every native select. This page lists the field controls, the metadata features the form honours, how values are collected, and how drafts work. The metadata classes are on metadata model.

Scope and source

  • Defined in: webapp/js/gen-form.js (createGenForm, makeGenFormView, mountRecordForm, buildRecordCard), webapp/js/form-drafts.js, webapp/js/customselect.js (initCustomSelects)
  • Count: 15 field types with a dedicated control, plus a plain text fallback (counted from the branches of controlHtml in webapp/js/gen-form.js:67-200); FieldMeta.field_type allows 19 values (src/cluster_erp/core/metadata.py:82-102)

Entry points

Function Purpose Source
createGenForm(moduleName, entityMeta, opts) Builds the form element and returns an object with loadFks, validate, showErrors, collect, commitFiles, setLocked, and draft helpers webapp/js/gen-form.js:287-1829
makeGenFormView(moduleName, entityMeta, opts) A pushed screen with the form, a parent picker when the create path needs {parent_id}, a document collector, and save webapp/js/gen-form.js:1846-2035
mountRecordForm(host, moduleName, entityMeta, opts) A read-only record card that switches to edit mode with Edit (common.edit) webapp/js/gen-form.js:2310

Field controls

field_type Control Value sent Source
string and unknown types Text input; semantic: "password" gives a password input Text webapp/js/gen-form.js:197-199
text, json Text area Text webapp/js/gen-form.js:72-74
integer Number input with min_value and max_value Integer webapp/js/gen-form.js:75-79, webapp/js/gen-form.js:495-498
float Text input with decimal keypad Number webapp/js/gen-form.js:80-82, webapp/js/gen-form.js:499-502
decimal Text input with decimal keypad The typed string, "0" when required and empty webapp/js/gen-form.js:80-82, webapp/js/gen-form.js:503-506
boolean Switch Boolean webapp/js/gen-form.js:83-88
date Date input YYYY-MM-DD or null webapp/js/gen-form.js:89-91, webapp/js/gen-form.js:511
datetime Local date-time input UTC ISO string webapp/js/gen-form.js:92-94, webapp/js/gen-form.js:512-514
file_upload File button; the file is uploaded on save Attachment id webapp/js/gen-form.js:95-105
enum Select; an optional field starts blank Choice value or null webapp/js/gen-form.js:106-116
multi_enum Toggle chips List of values webapp/js/gen-form.js:117-127
foreign_key Select filled from source, with a quick-create + when the source names an entity type Id webapp/js/gen-form.js:144-155
multi_foreign_key Toggle chips filled from source, with quick-create + List of ids webapp/js/gen-form.js:128-143
suggest_combo Text input with suggestions Text webapp/js/gen-form.js:156-164
dynamic_form Sub-fields loaded from the driver field's selected record Object webapp/js/gen-form.js:165-174
field_list Repeating rows of item_fields List of objects webapp/js/gen-form.js:175-184
string_list Removable chips with an input List of strings webapp/js/gen-form.js:185-195
hidden_scope_field No control; the value comes from the screen scope Scope value webapp/js/gen-form.js:390, webapp/js/gen-form.js:1775-1778

Decimal input stays a string from field to request. This follows the money rule on money and Decimal. The quick-create + carries the tooltip Quick create (fk.create_tooltip).

Metadata features honoured

Feature Behaviour Source
create_only and edit_only groups A create-only group is hidden when editing; an edit-only group is hidden when creating webapp/js/gen-form.js:290-298
conditional_group with condition Shown when the controlling field's value is in the pipe-separated set, inverted by negate; a controlling field that is not on the form is read from the loaded record webapp/js/gen-form.js:698-722
weight: "detail" The row is hidden until the user reveals detail rows webapp/js/gen-form.js:408-412
auto_generate Fills the field from a template when other fields match webapp/js/gen-form.js:434, webapp/js/gen-form.js:724-760
source.params with {parent_id} and {field:<key>} The picker reloads when the named sibling changes webapp/js/gen-form.js:816-900
immutable_on_edit Disabled on an existing record; a foreign key shows only the record's own option from a single read webapp/js/gen-form.js:845-860, webapp/js/gen-form.js:1632
read_only Disabled and not collected webapp/js/gen-form.js:1632, webapp/js/gen-form.js:1779
autofill Copies a field of the picked record into a sibling, optionally through another source webapp/js/gen-form.js:1180-1240
nested_key Values are read from and written to a nested object (with a <key>_info fallback on read) webapp/js/gen-form.js:1650-1662, webapp/js/gen-form.js:1768-1773
storage: "extra" A tenant-defined field travels in the row's extra bag webapp/js/gen-form.js:1656-1657, webapp/js/gen-form.js:1785-1790
EntityMeta.completeness A completeness bar with tiers above the form webapp/js/gen-form.js:465-480, webapp/js/gen-form.js:771-805
EntityMeta.composite_create A create posts one composite payload to the declared endpoint webapp/js/gen-form.js:39-56, webapp/js/gen-form.js:1990-2000
EntityMeta.photo A photo picked on the create form is uploaded to the new record's photo endpoint webapp/js/gen-form.js:2002-2012
EntityMeta.create_with_documents The create form collects documents and attaches them after creation webapp/js/gen-form.js:1914-1920

Validation and collection

validate() checks required fields in visible groups, including required sub-fields of container fields, and returns messages built from validation.field_required_named (webapp/js/gen-form.js:1696-1762). collect() skips hidden conditional groups and read-only fields, writes nested groups into their bucket, and never clears a loaded value whose option was not found (webapp/js/gen-form.js:1764-1794). commitFiles() uploads chosen files to POST /attachments/ and writes the returned ids before collect() runs (webapp/js/gen-form.js:1795-1812). The server validates again; see errors and exceptions.

Record card

mountRecordForm first shows a read-only card built by buildRecordCard (webapp/js/gen-form.js:2210-2308, webapp/js/gen-form.js:2440-2484). The card shows:

  • contact quick actions for record_actions (call, message, mail) (webapp/js/gen-form.js:2058-2077, webapp/js/gen-form.js:2449-2450);
  • the photo header when the entity declares photo (webapp/js/gen-form.js:2452-2460);
  • the Documents row (docs.section) unless record_documents is false (webapp/js/gen-form.js:2477-2483);
  • navigation bar entries: Share, Edit, and Actions when single_record actions apply (webapp/js/gen-form.js:2319-2361);
  • metadata links (RecordLinkMeta) that apply to the record; a link raises cluster:open-section with parameters taken from the record (webapp/js/gen-form.js:2364-2385).

In edit mode the navigation bar shows Cancel and Save (webapp/js/gen-form.js:2318-2322).

Drafts of unsaved input

form-drafts.js keeps only the fields the user changed from the loaded baseline (webapp/js/gen-form.js:1255-1271, webapp/js/form-drafts.js:1-16).

Rule Value Source
Draft key Module, entity, record id or new, parent id, and scope, joined by a vertical bar webapp/js/form-drafts.js:56-61
Storage Memory, mirrored to tab session storage under cluster.session.form_drafts webapp/js/form-drafts.js:18-51
Maximum drafts 60; the oldest is dropped webapp/js/form-drafts.js:20, webapp/js/form-drafts.js:94-104
Fields never stored Password fields and permission-gated fields webapp/js/gen-form.js:2043-2052, webapp/js/form-drafts.js:69-82
Cleared by Save, Cancel, closing the app from the switcher, and logout webapp/js/form-drafts.js:114-132, webapp/js/home.js:2539-2541
Restore notice A status line with a discard button webapp/js/gen-form.js:1830-1844

When a draft is restored, fields that depend on another field are filled after their controlling field, so dependent pickers find their options (webapp/js/gen-form.js:1273-1290).

Custom selects

initCustomSelects() runs at boot and upgrades every current and future native select through a MutationObserver. The native element stays as the source of truth for value and change events. A search box appears from 8 options (webapp/js/customselect.js:1-17, webapp/js/customselect.js:229, webapp/js/main.js:229).

Constraints and validation

  • The form never invents a status field. A status that changes only through actions is not on the form; a condition on it reads the loaded record (webapp/js/gen-form.js:703-707). See actions and action sheet.
  • Browser tests: web-client/_e2e_form_draft.mjs, web-client/_e2e_form_draft_matrix.mjs, web-client/_e2e_ui_forms.mjs, web-client/_e2e_party_form_fixes.mjs.

Terms introduced

Term Code identifier Definition Turkish term Source
record card mountRecordForm The read-only view of a record that switches to edit mode on request. kayıt kartı webapp/js/gen-form.js:2310
form draft writeDraft The session-only copy of the fields a user changed but has not saved. form taslağı webapp/js/form-drafts.js:84
quick create fk.create_tooltip The + next to a picker that creates a referenced record without leaving the form. Hızlı oluştur webapp/js/gen-form.js:146-148

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13