---
title: "Submission columns"
description: "Cross-form and automatic per-form submission columns."
requested_language: ar
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/ar/next/payload/forms/submissions
version: unreleased (main)
docs_index: https://docs.systhema.app/ar/next/llms.txt
---
> This page isn't translated yet. Showing English.


Every submission stores its answers in one `submissionData` array, so the list view's only real content is a relationship to the form and a count of answers — nothing about who wrote in.

Systhema makes the individual fields **addable as their own columns** from the list view's **Columns** menu. These are read-only **virtual** columns that resolve from `submissionData` at read time — nothing is stored, so adding or removing one never touches the database. They come in two flavours.

## Cross-form columns (`submissionColumns`)

Five declared columns — **Name, Email, Phone, Subject, Company** — that resolve against _whatever_ the submitted form calls that field. Matching is case- and separator-insensitive (`fullName`, `full_name`, `Full Name` are one name), tries aliases in priority order, and can join several fields into one value: the built-in **Name** column falls back to `firstName` + `lastName` when a form has no single name field.

Point `submissionColumns` at the names your own forms use to declare more; an array **replaces** the built-in set, and `false` removes them entirely:

```ts
forms: {
  submissionColumns: [
    'company',                                       // reads the `company` field
    { name: 'name', match: [['firstName', 'lastName']] },
    { name: 'budget', label: 'Budget', match: ['budgetRange', 'budget'] },
  ],
}
```

| Key     | Type                           | Default   | Description                                                                                           |
| ------- | ------------------------------ | --------- | ----------------------------------------------------------------------------------------------------- |
| `name`  | `string`                       | —         | Column accessor — usable in `formSubmissionOverrides.admin.defaultColumns`.                           |
| `label` | `StaticLabel \| LabelFunction` | humanized | Column header. Defaults to a humanized `name` (`budgetRange` → "Budget range").                       |
| `match` | `(string \| string[])[]`       | `[name]`  | Submitted field names to read, in priority order. A nested array joins the parts that were submitted. |

The built-in set is exported as `DEFAULT_FORM_SUBMISSION_COLUMNS` from `@systhemaui/payload`, so you can spread it and append rather than replace it.

## Per-form columns (automatic)

On top of those, **every field of every form** is registered as its own addable column, labelled `"<Form title>: <Field label>"` — `Contact: Email address`, `Hírlevél feliratkozás: Név`, `Partner application: Budget range`. The label comes from the form editor's own field label, so the Columns menu reads in the project's language and always says which form a column belongs to. Each column resolves only for submissions of _its_ form, so two forms with a same-named field never bleed into each other.

Forms are content, not config, so this set cannot exist when the Payload config is built. It is discovered from the database when the server starts, and refreshed whenever a form is saved — add a field to a form and its column appears in the Columns menu without a restart. A column for a field an editor **deleted** stays until the next restart (removing fields from a live config is riskier than leaving one that resolves to nothing).

Set `autoSubmissionColumns: false` to keep only the declared columns:

```ts
forms: {
  autoSubmissionColumns: false,
}
```

## Notes

Virtual columns are not sortable or filterable (there is no stored column to query), and they never appear in the submission's edit view, which keeps showing the full `submissionData` array. To have some active out of the box, list them in `formSubmissionOverrides.admin.defaultColumns` (the default is `['createdAt', 'form', 'submissionData']`). Worth knowing before you do: the export drawer seeds its **Fields** control from the list's active columns, so whatever you activate here also becomes the default export shape.

## Saving views

Payload's own [Query Presets](https://payloadcms.com/docs/query-presets/overview) save a list view's filters, columns and sort as a reusable, shareable preset — pair them with these columns to keep a "Contact form leads" view one click away. Opt in per collection with `formSubmissionOverrides: { enableQueryPresets: true }` plus a root-level `queryPresets: { access, constraints }` block on your Payload config.

Systhema also repairs the preset drawer's column picker. Payload builds its accessor → label map with `reduceFieldsToOptions`, a filter-oriented helper that deliberately drops `virtual: true` fields and flattens arrays, so every virtual column fell back to its raw accessor (`form_1_email`, `submissionData`) while the list view's own Columns menu read `Contact: Email address`. `withSysthema` swaps in a picker that takes labels from the same flattened client field list the table header uses, so both read alike. It applies to **any** collection with query presets and virtual fields, not just form submissions, and it steps aside if you supply your own component for that field.
