Skip to content

Rent a car: Introduction

This tutorial walks through building a complete Rent a Car form. By the end, you’ll have used most of the features GolemUI offers — layout, validators, states, custom item renderers, async data with debouncing, and form submission — in one connected example.

A form that lets a customer:

  • pick a car model from a dropdown (search-as-you-type, custom item renderer with image and details),
  • pick a collect-from office dropdown,
  • toggle “Choose a different return location” to reveal a return-to office dropdown,
  • pick a rental dates range (a range calendar),
  • pick a rental type from a radio group,
  • confirm the driver is aged over 25 with a toggle,
  • toggle “I have a discount code” to reveal a discount code input,
  • submit the form, with the submit button disabled until everything is valid.

Work through them in order — each chapter builds on the previous one.

  1. Parts of the form — author the static layout with all the input widgets.
  2. States and conditional rendering — wire the toggles to show/hide fields.
  3. Validation errors — wire validators to every required field, then replace the default Zod messages with friendlier copy.
  4. A custom item renderer — design the per-car list item with image, name, and price.
  5. Search as you type — load the car list from a service, filter server-side, debounce the input.
  6. Submitting the form — capture the submit event and read the data.

This tutorial follows the GolemUI default:

gui.layouts.grid for rows (CSS subgrid keeps labels and inputs aligned), gui.layouts.flex for columns.

In Installation we authored the form definition inline, in the same file as the React / Angular / Lit / Vue component (or in main.js for vanilla JS). That keeps everything in one place while you’re getting started, but for any non-trivial form it’s a maintenance trap — the component file balloons, and reusing the form shape from a test, a script, or a backend becomes awkward.

From this chapter on, the tutorial moves the form definition into its own dedicated file:

rent-a-car.form.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dropdown('car', {
/* ... */
}),
// …more widgets…
];

Then import that form from your component and pass it as formDef in the config object. The wiring code is identical to what you saw in Installation — only the source of formDef changes.

rent-a-car.page.tsx
import { GuiForm } from '@golemui/gui-react';
import rentACarForm from './rent-a-car.form';
export function RentACarPage() {
return <GuiForm config={{ formDef: rentACarForm }} />;
}

The wiring above stays the same as the form grows; only the form definition file changes.