dbxapp Knowledge dbxForm

dbxForm

On this page
  1. dbxForm: forms as one controlled pipeline
  2. 1. Where dbxForm belongs
  3. 2. One form run, one state model
  4. 3. DD and FD responsibilities
  5. 4. Initialization
  6. 5. Values and validation
  7. 6. Saving records
  8. 7. Callbacks without hidden coupling
  9. 8. Messages and error presentation
  10. 9. Ajax is an interaction mode
  11. 10. Embedded and repeated forms
  12. 11. Security and acceptance checklist
Core library · dbxapp 4.5.3

dbxForm: forms as one controlled pipeline

dbxForm connects DD and FD definitions, request values, validation, messages, form state, Ajax rendering, and persistence. It is a stateful facade for one form run, not merely an HTML helper.

1. Where dbxForm belongs

Use dbxForm whenever a module accepts structured input or changes a record. The router selects the route, the service configures the form, DD and FD provide the data and field contracts, and dbxTPL renders the result. Domain rules stay in the service; database and UI infrastructure stay in the system classes.

2. One form run, one state model

  1. Load the initial record through dbxDB and the DD.
  2. Resolve the FD and its language-specific messages.
  3. Merge request values over the initial values for a submitted form.
  4. Normalize and validate every accepted field on the server.
  5. Retain normalized values, field errors, global messages, and submit protection.
  6. Persist only after the complete validation result is valid.
  7. Render the current state through dbxTPL.

This sequence is why dbxForm is intentionally stateful. Splitting it into unrelated public helper objects would make modules coordinate state that the form pipeline already owns.

3. DD and FD responsibilities

ContractDefinesDoes not define
DDTable, fields, types, indexes, ownership, and permissionsPage layout
FDVisible fields, order, labels, view options, and messagesDuplicate database permissions
ServiceDomain rules and orchestrationDriver-specific persistence
TemplateForm structure and placeholdersValidation or authorization

Keep message keys identical across language variants. Load visible labels and validation text from the FD so that the form, its errors, and its Ajax response remain synchronized.

4. Initialization

$form = dbx()->get_system_obj('dbxForm');
$form->init('invoice-form', $invoiceDd, $invoiceFd, $rid);
$form->set_tpl('myInvoices|invoice-form');
return $form->run();

The form ID is the stable identity for callbacks, DOM state, messages, and Ajax replacement. The callback owner defaults to the module or service that creates the form. Configure a different owner only when the architecture deliberately requires it.

5. Values and validation

For a new request, initial DD values form the baseline. On submit, accepted request values take precedence so that invalid input can be shown again without losing the user’s work. Unknown fields are ignored; accepted values are normalized and validated against the FD and DD contracts.

Use server-side callbacks for cross-field or domain validation. A client-side check may improve feedback, but it must never be the only safeguard.

6. Saving records

save_post() performs the standard insert or update through dbxDB. Permissions, allowed fields, automatic audit values, tracing, and database abstraction remain active. After an insert, store the returned RID in the form action with set_rid_in_action(); the next submit then updates that record.

7. Callbacks without hidden coupling

The conventional callback name is derived from the form ID and event, represented as {fid}_{event}. This keeps the relationship visible and avoids repetitive callback registration. Use explicit callbacks only when a well-documented variation requires them.

Callbacks may add normalized values, domain errors, or replacement values. They must not print HTML, perform undisclosed redirects, or reimplement request and permission checks.

8. Messages and error presentation

Field errors stay with their fields. Global success, warning, and error messages use the shared form message pipeline. A normal response and an Ajax response must expose the same result and the same translated message; only the replacement scope differs.

9. Ajax is an interaction mode

Add the established dbxAjax attributes to the form and identify the 1 root that should be replaced. The server runs the same route, validation, persistence, and template code as a normal POST. After replacement, the runtime reinitializes the features required by the new fragment.

Always test the form with JavaScript disabled. If the normal POST is incomplete, the Ajax path is masking an architectural defect.

10. Embedded and repeated forms

Give every instance a unique form ID and DOM root. Do not nest HTML <form> elements. When a child editor belongs inside a larger view, render it as a separate window or replaceable region with its own state and submission boundary.

11. Security and acceptance checklist

  • Module access and DD write permissions are checked.
  • Only declared fields reach validation and persistence.
  • Insert, update, invalid input, and a repeated submit are covered.
  • The form works without JavaScript and through Ajax.
  • Two instances do not share IDs, values, callbacks, or messages.
  • Visible labels and all success and error messages are verified in German and English.
  • The browser console, Missing counters, files/dbxError.log, PHP logs, and system messages remain clean.
Next stepSee dbxForm working together with dbxReport, DD, Ajax, and permissions in one complete module.Open the Module Manual