AppFormRow
Arrange form fields in a responsive grid.
<app-form-row><app-form-row> organises multiple form fields in a flexible CSS grid with a configurable column count (1, 2, or 3). The grid automatically collapses to a single column on mobile devices (below the md breakpoint), ensuring fields stay readable on every screen size.
Pair it with <app-form-section> to group related fields and <app-form-actions> to anchor action buttons at the form's end.
Playground
Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the grid above it.
Basic usage — a two-column field grid
By default, AppFormRow arranges fields in 2 columns that collapse to 1 on phones.
<app-form-row columns="2">
<app-input label="First name" name="firstName" />
<app-input label="Last name" name="lastName" />
</app-form-row>
Column counts — 1, 2, or 3
Set the columns attribute to control how many fields sit in a row on desktop screens.
One column (full width)
Three columns
<!-- One column -->
<app-form-row columns="1">
<app-input label="Full width field" name="fullName" />
</app-form-row>
<!-- Three columns -->
<app-form-row columns="3">
<app-input label="Day" name="day" />
<app-input label="Month" name="month" />
<app-input label="Year" name="year" />
</app-form-row>
Responsive breakdown
All column counts collapse to a single column below the md breakpoint (768px). This ensures fields stay appropriately sized and readable on phones. Resize your browser window or view on a phone to see the grid collapse to 1 column.
Spacing
<app-form-row> uses theme gap tokens to ensure consistent spacing between fields. The gap is applied both horizontally (between columns) and vertically (between rows on mobile), matching the design system's spacing scale.
Supported children
<app-form-row> works with any form field component:
<app-input>,<app-textarea>,<app-number-input><app-select>,<app-select-mini>,<app-autocomplete>,<app-multi-select>,<app-tag-input><app-checkbox>,<app-radio>,<app-switch><app-date-picker>,<app-date-range-picker>,<app-time-picker><app-phone-number-input>,<app-color-field>,<app-slider>
Every option
The whole surface of the component, one cell per value — column counts, class forwarding, passthrough attributes, mixed field types, and long content wrapping inside a narrow column.
columns — all three
columns="1"
columns="2"
columns="3"
class — merged onto the grid div
class="row-highlight"
passthrough props — id, data-*, style
id="shipping-row" data-testid="row"
style="margin-top: 24px" — merged with the component's own --form-cols declaration, same as React (see Attributes)
mixed field types
app-input + app-textarea + app-checkbox in one row
long content — a label that wraps inside a narrow column
columns="3" with a long field label
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| (content) * | — | — | Field components (app-input, app-select, etc.) laid out in the grid. |
| columns | 1 | 2 | 3 | 2 | Number of columns at desktop width. Collapses to 1 column below md breakpoint (768px). |
| class | string | — | Extra classes merged onto the grid div (component classes go first, so an authored class wins the cascade). |
| style | string | — | Extra inline styles merged with the component's own --form-cols declaration (component declaration first, so an authored property of the same name wins). |
When to use
Use it when
- You have multiple form fields that should sit side-by-side on desktop but stack on mobile.
- You are building a form page with multiple rows of fields (pair with AppFormSection to group them).
- You need responsive column control without custom CSS — use the columns attribute.
Reach for something else when
- You need a single full-width field. → Just use the field component directly, or wrap in columns="1"
- You need a custom grid layout (asymmetric columns, spans, etc.). → Use Bootstrap Row/Col for full control
- You are organizing logical groups, not just laying out fields. → Wrap AppFormRow in AppFormSection to add a title and description