# Collect User Input

Build forms, validate data, and react to user input in Blazor.

- Repository: https://github.com/dotnet/skills (5787 stars)
- Category: Design
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add dotnet/skills --skill collect-user-input -g -a claude-code -y`
Codex: `npx skills add dotnet/skills --skill collect-user-input -g -a codex -y`
Cursor: `npx skills add dotnet/skills --skill collect-user-input -g -a cursor -y`
Gemini CLI: `npx skills add dotnet/skills --skill collect-user-input -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add dotnet/skills`

## Description

Build forms, validate data, and react to user input in Blazor. USE FOR adding forms, search boxes, filter panels, inline editing, data-entry UI, file uploads, validation (annotations or custom), handling form submissions, and binding input controls. Covers EditForm, built-in input components, DataAnnotationsValidator, custom validation, SSR form patterns (SupplyParameterFromForm, FormName, AntiforgeryToken, Enhance), and @bind for simple interactive controls. DO NOT USE for project scaffolding (see create-blazor-project) or prerendering issues (see support-prerendering).

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Collect User Input

## Step 1, Read the Project's AGENTS.md

Check `AGENTS.md` for **Interactivity Mode** and **Interactivity Scope**. This determines which form patterns apply:

| Mode | Form mechanism |
|------|---------------|
| None (Static SSR) | `EditForm` with `FormName` + `[SupplyParameterFromForm]`. No `@bind`, no `@onchange`. |
| Server | `EditForm` with `@bind-Value`. Full interactivity, real-time validation, dynamic UI. |
| WebAssembly | Same as Server, but validators needing server data must call APIs. |
| Auto | Same as WebAssembly, code must work in both browser and server. |

| Scope | Impact |
|-------|--------|
| Global | All forms are interactive. `FormName` only needed when explicitly opting a page to static SSR. |
| Per-page | Forms in static pages use `FormName` + `[SupplyParameterFromForm]`. Forms in `@rendermode` pages use `@bind-Value`. |

## EditForm Setup

`EditForm` requires **either** `Model` or `EditContext`, never both.

### Model-based (default)

```razor
<EditForm Model="Employee" OnValidSubmit="HandleSubmit" FormName="employee">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <label>
        Name: <InputText @bind-Value="Employee!.Name" />
        <ValidationMessage For="() => Employee!.Name" />
    </label>

    <button type="submit">Save</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private EmployeeModel? Employee { get; set; }

    protected override void OnInitialized() => Employee ??= new();

    private async Task HandleSubmit()
    {
        // Save Employee
    }
}
```

This single pattern works in **both** SSR and interactive modes:
- In SSR: `FormName` identifies the form, `[SupplyParameterFromForm]` binds POST data, `??=` initializes on GET.
- In interactive: `@bind-Value` provides two-way binding, `[SupplyParameterFromForm]` is ignored, `FormName` is harmless.

### EditContext-based (advanced)

The rest: https://github.com/dotnet/skills/blob/HEAD/plugins/dotnet-blazor/skills/collect-user-input/SKILL.md
