Ajax Form
Ajax Forms combine form submission, API communication, and automatic response rendering. They allow you to submit without page reload, load entity data into inputs, and apply API responses directly to the UI.
Goals
- Submit without page reload
- Handle POST to PUT transitions
- Render API responses into the DOM
Related Classes
Steps
Classes used in this pattern
| Class | Role |
|---|---|
| CotomyApiForm | API submit lifecycle |
| CotomyEntityApiForm | POST to PUT transitions using an entity key |
| CotomyEntityFillApiForm | Apply API responses to the UI |
Form capabilities
| Form | API submit | Entity key | Renderer | Auto fill | Notes |
|---|---|---|---|---|---|
| CotomyForm | No | No | No | No | Submit lifecycle only |
| CotomyQueryForm | No | No | No | No | GET query navigation |
| CotomyApiForm | Yes | No | No | No | Sends FormData to API |
| CotomyEntityApiForm | Yes | Yes | No | No | POST to PUT by entity key |
| CotomyEntityFillApiForm | Yes | Yes | Yes | Yes | Loads and fills from API responses |
1) Prepare HTML
<form id="profile-form" action="/api/profile" method="post">
<input name="name" />
<input name="email" />
<button type="submit">Save</button>
<div class="result">
<span data-cotomy-bind="name"></span>
<span data-cotomy-bind="email" data-cotomy-bindtype="mail"></span>
</div>
</form>
Inputs are for submission. Elements with data-cotomy-bind are for display. The same data flows into both.
2) Bind the form to Cotomy
import { CotomyEntityFillApiForm } from "cotomy";
const form = CotomyEntityFillApiForm.byId(
"profile-form",
CotomyEntityFillApiForm
)!;
form.initialize();
CotomyEntityFillApiForm submits with FormData and applies successful API responses to elements with data-cotomy-bind.
initialize() must be called once to enable Cotomy's submit lifecycle.
If the form already has an entity key, it automatically loads data when the page becomes ready.
3) Submit flow
When submitted:
- FormData is created
- The API request is sent
- If 201 Created, the entity key is stored
- Response JSON is applied to the DOM
This is a server-driven UI update model: the response is the source of truth.
4) POST to PUT transitions
When the server responds with 201 Created and a Location header, Cotomy stores the entity key. Subsequent submits switch from POST to PUT automatically.
Using the server-issued Location keeps identity authoritative and avoids duplicate creates in CRUD flows.
5) Bind name styles and renderers
data-cotomy-bind marks where values are rendered. data-cotomy-bindtype can format values (mail, tel, url, number, utc, date) during rendering.
<span data-cotomy-bind="email" data-cotomy-bindtype="mail"></span>
The renderer turns the value into a mail link automatically.
data-cotomy-bindtype only affects rendering, not form submission.
For utc and date, rendering is local by default; add data-cotomy-timezone (element or ancestor) to render in a specific IANA timezone.
How Rendering Works
CotomyEntityFillApiForm uses CotomyViewRenderer internally. The renderer:
- Reads JSON from the API response
- Matches values to data-cotomy-bind
- Updates the DOM elements
The renderer updates:
- Elements with data-cotomy-bind
- Matching form inputs (by name)
It does not modify unrelated DOM elements.
data-cotomy-bind is only used when a renderer is involved. Forms that do not use CotomyViewRenderer (such as plain CotomyForm or CotomyApiForm) will ignore these attributes.
Rendering does not change submission behavior. It only updates display elements and inputs. fill updates inputs; render updates display elements.
The renderer clears bound elements first, then applies data from the response. Keys that are missing in the response are cleared.
If the API request fails, rendering is skipped and error events are triggered.
6) Advanced: switch to dot notation
By default, Cotomy uses bracket-style bind names such as user[name]. If you prefer dot notation like user.name, set the page default bind name generator:
import {
CotomyDotBindNameGenerator,
CotomyEntityFillApiForm,
CotomyPageController
} from "cotomy";
CotomyPageController.set(class extends CotomyPageController {
protected override async initializeAsync(): Promise<void> {
this.defaultBindNameGenerator = new CotomyDotBindNameGenerator();
this.setForm(CotomyEntityFillApiForm.byId(
"profile-form",
CotomyEntityFillApiForm
)!);
}
});
Important Concept: Ajax Forms Use the Same DOM Model
Cotomy does not create a separate form state. Inputs and bound elements are still normal DOM nodes, and the API response is applied explicitly through the renderer.
What just happened?
You:
- Bound a form to Cotomy's API submit lifecycle
- Submitted without a page reload
- Switched to PUT after creation
- Applied API responses to the DOM
You now have a form that loads data, submits to an API, updates the UI, and manages entity identity.
Next
Next: Page Control to coordinate page-level behavior.