Skip to content

Rent a car: Parts of the form

In this chapter you’ll declare every input the form needs, in a sensible order, with no logic yet. The form ends up rendering all the pieces but doesn’t react to anything — that’s what the next chapters add.

GolemUI ships two layouts that cover most needs:

  • gui.layouts.grid for rows. Subgrid alignment keeps labels, inputs, and validation messages aligned across all children in a row.
  • gui.layouts.flex for columns. Lighter, more flexible for vertical stacks.

The top-level form definition is implicitly stacked vertically (the engine adds an auto-stack — see Sensible defaults), so we only need a grid when we want fields side-by-side.

The two office dropdowns sit side-by-side in a row, the rest stacks vertically.

01-form.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dropdown('car', {
labelField: 'label',
valueField: 'id',
items: [
{
id: 'compact',
label: 'Compact',
},
{
id: 'suv',
label: 'SUV',
},
{
id: 'convertible',
label: 'Convertible',
},
{
id: 'luxury',
label: 'Luxury',
},
],
label: 'Select car',
}),
gui.layouts.grid([
gui.inputs.dropdown('collectOffice', {
labelField: 'label',
valueField: 'id',
items: [
{
id: 'lhr',
label: 'London Heathrow',
},
{
id: 'cdg',
label: 'Paris CDG',
},
{
id: 'fra',
label: 'Frankfurt Main',
},
],
label: 'Collect from office',
}),
gui.inputs.dropdown('returnOffice', {
labelField: 'label',
valueField: 'id',
items: [
{
id: 'lhr',
label: 'London Heathrow',
},
{
id: 'cdg',
label: 'Paris CDG',
},
{
id: 'fra',
label: 'Frankfurt Main',
},
],
label: 'Return to office',
}),
], {
direction: 'row',
autoFit: true,
}),
gui.inputs.booleanInput('differentReturn', {
label: 'Choose a different return location',
}),
gui.inputs.rangeCalendar('rentalDates', {
label: 'Rental dates',
}),
gui.inputs.radiogroup('rentalType', {
options: [
{
label: 'Daily',
value: 'daily',
},
{
label: 'Weekly',
value: 'weekly',
},
{
label: 'Monthly',
value: 'monthly',
},
],
label: 'Rental type',
}),
gui.inputs.booleanInput('driverOver25', {
label: 'Driver aged over 25',
}),
gui.inputs.booleanInput('hasDiscountCode', {
label: 'I have a discount code',
}),
gui.inputs.textInput('discountCode', {
label: 'Discount code',
}),
gui.actions.button({
label: 'Reserve',
uid: 'submit',
onClick: 'submit',
}),
];

Notice that the Return to office dropdown is visible all the time, and the Discount code input is too. We’ll fix both with states in the next chapter.

States and conditional rendering →