How to define a form
A recipe for the metadata rows that produce a working module + form in BACK and FROUNT. Use this when you want to add a new screen without writing Java.
What you'll insert
Three rows, in order, in three tables. Plus optional rows for fields, permissions, and document numbering.
1. The module — gdsmodule
One row registers the module's existence. Required columns:
| Column | Value |
|---|---|
sId |
unique ID — use the IdGen next-id helper, or any 32-char string not already taken |
sName |
the URL fragment, e.g. /indexPage/commonList (use a shared page-template URL — see Slice 3) |
sChinese / sEnglish / sBig5
|
display name in three languages |
sParentId |
parent module's sId — places this module in the menu tree |
sBrandsId / sSubsidiaryId
|
tenant scope — should be your tenant's IDs (or '1111111111' if standard / system-level) |
sVersionFlowId |
the product edition this module belongs to (look up in sisversionflow) |
bVisible |
1 to show in the menu |
bInvalid |
0 for active |
Leave sSaveProName, sDeleteProName, sCalcProName, sProcName,
sSaveProNameBefore empty unless you need custom CRUD (see the runtime
reference).
2. The form-master — gdsconfigformmaster
One row per form per module. Required:
| Column | Value |
|---|---|
sId |
unique form ID |
sParentId |
the module's sId from step 1 |
sTbName |
the backing object's name — a real table, view, or proc |
sType |
'table', 'view', or 'proc'
|
sSqlStr |
the read SQL skeleton; usually SELECT ... FROM {sTbName} WHERE ...
|
sWhere |
default WHERE predicates (the runtime adds tenant filters automatically) |
sOrder |
default ORDER BY |
iPageSize |
rows per page in the grid |
bGrd |
1 if a grid layout, 0 if a single-record form |
sBrandsId / sSubsidiaryId
|
tenant scope |
For a read-only report, use sType = 'view' and point sTbName at a
viw_* view. The framework will not render
save/delete buttons.
3. The fields — gdsconfigformslave, one row per field
Most-used columns (the table has 60+, most have sane defaults):
| Column | Value |
|---|---|
sId |
unique field ID |
sParentId |
the form's sId from step 2 |
iOrder |
sort order in the grid |
sName |
the column name on the backing object |
sChinese / sEnglish / sBig5
|
display label |
sControlName |
UI control type — 文本框 (textbox), 下拉框 (dropdown), 日期 (date), 数字 (number), … |
bVisible |
1 to show |
bNotEmpty |
1 to require |
bReadonly |
1 for display-only |
bCanInput |
1 for editable |
iColValue |
column-span in form layout |
sDefault |
default value |
sChineseDropDown |
dropdown SQL (if applicable) — SELECT sId AS sValue, sChinese AS sText FROM …
|
sActiveId / sActiveKey
|
for popup-lookup controls — refers to another module |
Optional layers
Document numbering — sysbillnosettings
If the module's records need auto-generated bill numbers (work-order
numbers, quotation numbers, etc.), add a row here keyed by the form's
sId. The runtime returns this in the getModelBysId response under
billnosetting.
Permissions — gdsjurisdiction
See How to set permissions. One row per (module, button-or-data, role) tuple.
Tenant overrides
A tenant who wants a different view of this form inserts rows into
gdsconfigformpersonalize (form-level override) or
gdsconfigformcustomslave (field-level override). See
Slice 4.
Verifying
Once all rows are inserted, the SPA's next request to
getModelBysId/{your-module-sId} should return your form's metadata.
Click the new sidebar item — the form should render. If it doesn't:
- Check
bVisible = 1ongdsmodule. - Check that
gdsroutehas an entry for the URL (one is auto-added in most deployments). - Check
sBrandsId/sSubsidiaryIdon every row match the user's tenant. - Check that the form's
sParentIdmatches the module'ssIdexactly — semantic FK, no cross-row check at write time.
Cache invalidation
After inserting, the runtime's cache holds the previous (empty) state
until a JMS message fires. xly's cache-invalidation listener
(ConsumerChangeGdsModuleThread) handles this when the BACK builder
saves changes; if you're inserting via raw SQL, you may need to bounce
the running services or wait for the TTL to expire. See
Cache invalidation on metadata change.