Skip to content

Forms & Data Validation Index

Easily build responsive forms in Wappler and ensure data quality with client-side and server-side validation tools. Prevent errors, provide user feedback, and c

Use the Demo Projects HQ login form to see how one submit flow can redirect on success, stay put on failure, and still keep the user oriented.

Login shows a split success and failure path

Section titled “Login shows a split success and failure path”

The Demo Projects HQ login page is useful because success and failure do not end in the same place. A valid login redirects into the app, while invalid credentials keep the user on the page with focused feedback. That is the real submission contract this tour explains.

A successful submit can navigate away.
A failed submit should preserve context on the same page.
The form should make both outcomes understandable without guessing.

The login form owns both redirect and error behavior

Section titled “The login form owns both redirect and error behavior”

#login_form is more than a submit wrapper. It posts to the login action, redirects with browser.goto('/') on success, and keeps its error branches on the same page when authentication fails. That makes it a good example of a form with asymmetric outcomes.

A successful login should not simply clear the form and stay put. Demo Projects HQ redirects into the app because the user’s context has genuinely changed. That makes the success branch feel final instead of ambiguous.

The submit control shows the request is in flight

Section titled “The submit control shows the request is in flight”

#login-submit disables itself and swaps into a signing-in state while the request is executing. That keeps the redirect path honest too, because the user can see the form is actively working before the page changes.

When login fails, the page stays where it is and uses focused error branches for invalid credentials and broader request failures. That is the right counterweight to success redirects: the form preserves context when the user still has work to do.

The login page works because the submit flow resolves in two honest directions: a successful session leaves the page, while a failed session stays on the page with focused feedback. That is the right pattern whenever a form has a meaningful post-submit branch.

Redirect only when success really changes context.
Keep failure feedback local to the same form.
Let the user understand both outcomes immediately.

Use the Demo Projects HQ task form to see where number fields, scheduling inputs, and richer widgets each belong in a practical form.

Some values need more structure than plain text

Section titled “Some values need more structure than plain text”

The task form goes beyond ordinary text fields because time, estimates, and multi-value tags become hard to manage when they are treated as undifferentiated strings. Wappler gives you better field types and widgets when the data shape really calls for them.

Use number fields when arithmetic or boundaries matter.
Use date and time pickers when users are scheduling real moments.
Use richer widgets when one value needs guided lookup or structured multi-select behavior.

The task form shows where basic fields stop being enough

Section titled “The task form shows where basic fields stop being enough”

The task page mixes ordinary inputs with more specialized ones because the data shape changes across the form. Estimates behave like measurable numbers, scheduling fields need real date-time structure, and tags need a clearer multi-value editing surface than a comma-separated text box.

Estimates and logged hours should stay numeric

Section titled “Estimates and logged hours should stay numeric”

#task_estimate and #task_logged are number fields because the values participate in arithmetic and boundary rules. Treating them as numbers early makes validation, calculation, and reporting much easier than collecting them as plain text and cleaning them up later.

Start and due times need scheduling controls

Section titled “Start and due times need scheduling controls”

#task_start and #task_due are where a plain text box becomes too ambiguous. Once users are choosing real schedule values, date-time pickers reduce formatting mistakes and keep the two time fields consistent with how the application actually uses them.

Project and tags cross into richer widget territory

Section titled “Project and tags cross into richer widget territory”

#task_project and #task_tags show the point where the page needs guided lookup or structured multi-selection instead of a plain control. That is not a reason to make every field fancy. It is a reason to escalate only where the user would otherwise fight the input.

The task form shows the dividing line clearly: number inputs help with measurable values, schedulers help with real date-time choices, and richer widgets help when a field needs more guidance than a plain control can provide. The key is to escalate only when the data shape actually justifies it.

Stay simple when a plain field is enough.
Add structure when mistakes would become expensive or confusing.
Use the widget tours for the deeper implementation details.

Start with Forms guides that show the main form-building path, then branch into validation and multi-step flows.

Choose a Forms guide to start.

Get a quick overview of Forms: what it is, where to find it, and how it fits in your workflow.

Forms are where user input, validation, and submission logic meet, so it helps to start with a clear map. This quick overview points out the main building blocks in Wappler, shows how the pieces connect, and prepares you for the focused tours on layout, validation, and repeatable sections.

Forms are built from components (Form, inputs, buttons, validators).
You can validate input in the browser and on the server.
Server Actions process submissions securely (DB, email, files).

Add a form to your page from the Components picker. You can use predefined form templates or build your own from scratch.

Insert a Form component on the page.
Add input fields and a submit button.
Bind values and add validation rules.

Add form elements like text inputs, textareas, selects, checkboxes, radio buttons, and file uploads. All styled with Bootstrap.

Use labels/placeholders for clarity.
Group fields with layout components (rows/columns).
Use input types that match your data (email, number, date).

Add the Form Validator component to validate user input both client-side and server-side. Set rules for required fields, email formats, and more.

Client-side validation improves UX with instant feedback.
Server-side validation protects your backend.
Show clear messages so users can fix issues quickly.

Connect your form to a Server Action to process the data.

Use Server Actions to handle submissions securely.
Store data in a database or send emails.
Revisit the Forms hub for focused how-tos.

Use the Demo Projects HQ task form to separate simple status choices from relationship fields that point at live project and contact records.

Choice fields split into two different jobs

Section titled “Choice fields split into two different jobs”

The task form in Demo Projects HQ shows that not every choice field means the same thing. Some fields just choose from a fixed vocabulary like status or priority. Others point at a real related record such as a project or contact, which changes how the field should be designed and validated.

Static choices express a closed set of meanings.
Relationship fields point at real records.
The UI may look similar, but the data contract is different.

The task form mixes fixed choices with live lookups

Section titled “The task form mixes fixed choices with live lookups”

task_add.ejs is useful because it puts both patterns in one place. Status and priority are fixed meaning sets, while project and assignee connect the task to live records the rest of the application already knows about.

Status and priority are closed vocabularies

Section titled “Status and priority are closed vocabularies”

#task_status and #task_priority are not asking the user to discover outside data. They are asking the user to choose from a small set of meanings the system already defines, which is exactly what a plain select handles well.

Project is a relationship field, not just a dropdown

Section titled “Project is a relationship field, not just a dropdown”

#task_project looks like one control, but its job is different from status or priority. It has to point at a real project record, which is why the form treats it as a required relationship and supports guided lookup instead of leaving the user with a long static list.

Assignee shows the editable relationship pattern

Section titled “Assignee shows the editable relationship pattern”

#task_assignee is the related-record pattern in a more traditional select shape. The important part is not the control chrome. It is that the stored value still points at a contact id, and the form deliberately allows an Unassigned fallback instead of implying every task must have a contact.

Choice fields become easier to maintain when you separate closed vocabularies from related-record selection. That distinction is what tells you whether a plain select is enough or whether the field needs a stronger data-driven pattern.

Keep fixed vocabularies simple and explicit.
Treat related-record fields as real data lookups.
Move into the dynamic select tour when the option list comes from live data.

Use the Demo Projects HQ task form to connect page fields, the Server Connect form action, and the success/error states that come back after submit.

A form submit is a contract with a server action

Section titled “A form submit is a contract with a server action”

The new-task page in Demo Projects HQ is a good baseline because it does not stop at field collection. The form, its action URL, its success branch, and its error state all live together on one page, so the handoff from browser input to server processing stays readable.

The page form decides what gets posted.
The Server Connect action decides what happens to that payload.
The page still needs clear success and error states after the request returns.

#task_form is the browser-side handoff boundary. It gathers the page inputs, names the action endpoint, and becomes the object that exposes success data, request state, and lastError after submit.

The action URL is the server-side contract

Section titled “The action URL is the server-side contract”

This form posts to /api/tasks/insert, which is the point where field input stops being just page state and becomes a request for the server to process. Keeping that contract explicit is what makes form behavior explainable later when insert, update, and validation rules evolve.

The save button is disabled while task_form.state.executing is true, so the page makes the request lifecycle visible instead of leaving the user to guess whether the form started working. That feedback belongs to the same submit contract as the action URL itself.

The page owns the success and error return path

Section titled “The page owns the success and error return path”

The same form also decides how returned state is shown. Demo Projects HQ keeps success and server failure messages on the page through task_form.data and task_form.lastError, which means the handoff is complete only when the user can see the result.

A reliable form workflow does not stop at a submit button. It stays readable from the page fields through the Server Connect action and back into visible result states, so the user can tell what the form is doing and what happened afterwards.

Know which action the form is posting to.
Keep result feedback on the same page contract.
Pair the handoff with validation and pending-state clarity.

Use the Demo Projects HQ client form to choose plain text-style fields that match names, email addresses, phone numbers, and short supporting details.

Plain fields still need deliberate choices

Section titled “Plain fields still need deliberate choices”

Demo Projects HQ uses the client form to show the everyday input decisions that shape data quality before any richer widgets are needed. The important question is not whether a field looks basic. It is whether the field type matches the kind of value the page is asking the user to provide.

Use text inputs for flexible human-readable values.
Use specialized input types when the browser can help the user.
Keep the field contract honest about what the backend expects.

The client form is a clean plain-fields baseline

Section titled “The client form is a clean plain-fields baseline”

client_add.ejs is a good reference because it stays readable while still covering the everyday fields many projects need first: name, email, phone, status, and city. That makes it easier to see where ordinary form controls are enough before richer widgets enter the picture.

#client_name is a plain text field because names are human-readable values with too many edge cases for a tighter format. The right constraint here is not a fancy widget. It is a reasonable required rule and sensible length limits.

#client_email is the point where a specialized field starts helping instead of getting in the way. Using an email input keeps the control familiar while giving the browser and validator a clearer contract than a generic text box would.

#client_phone and #client_city show the value of restraint. These fields often need flexibility because formatting varies by user and region, so a plain text input is usually the more honest starting point unless the project has a much stricter data policy.

The client form works because each plain field matches the kind of value it collects instead of treating everything as generic text. Once the field types are sensible, validation becomes much easier to explain and maintain.

Choose the simplest field that honestly matches the data.
Let browser-aware input types help where they can.
Add validation after the field contract is clear.

Browse Forms tours: Quick Overview, Validation, and Multi-Step.

Choose a Forms guide to start. These guides now lean on real Demo Projects HQ pages such as task_add.ejs, task_edit.ejs, login.ejs, and files.ejs so the patterns stay tied to concrete fields, buttons, and feedback states instead of floating as generic advice.