b530bb8c97
Co-authored-by: Copilot <copilot@github.com>
194 lines
6.0 KiB
Markdown
194 lines
6.0 KiB
Markdown
# Checkbox
|
|
|
|
A styled checkbox with an optional text label. Use it in forms when you want the user to opt in or out of something — "Remember me", "I agree to the terms", or selecting items in a list.
|
|
|
|
---
|
|
|
|
## Quick example
|
|
|
|
```csharp
|
|
new Checkbox(
|
|
id: "newsletter",
|
|
label: "Subscribe to newsletter",
|
|
name: "newsletter")
|
|
```
|
|
|
|
---
|
|
|
|
## All the options
|
|
|
|
```csharp
|
|
public Checkbox(
|
|
string id,
|
|
string label = "",
|
|
string name = "",
|
|
string value = "true",
|
|
bool @checked = false)
|
|
```
|
|
|
|
| Parameter | What it does |
|
|
|---|---|
|
|
| `id` | The element id. Also used by the `<label for="...">` so clicking the label toggles the box. |
|
|
| `label` | Visible text next to the checkbox. Leave empty for a standalone checkbox with no label. |
|
|
| `name` | Form field name — required if you want the value submitted with the form. |
|
|
| `value` | The string that gets submitted when the box is checked. Defaults to `"true"`. |
|
|
| `checked` | Pre-tick the checkbox on render. |
|
|
|
|
---
|
|
|
|
## Real-world examples
|
|
|
|
### Terms and conditions on a registration form
|
|
|
|
```csharp
|
|
new Checkbox(
|
|
id: "terms",
|
|
label: "I agree to the terms of service",
|
|
name: "terms",
|
|
value: "accepted")
|
|
```
|
|
|
|
Reading it on the server:
|
|
|
|
```csharp
|
|
public record Command(
|
|
[property: FromForm] string? Terms = null // null when unchecked, "accepted" when checked
|
|
);
|
|
|
|
bool agreedToTerms = command.Terms == "accepted";
|
|
```
|
|
|
|
> **Important:** HTML forms only submit checkboxes that are *checked*. An unchecked checkbox sends nothing — the field is simply absent. Always use a nullable string (`string?`) or give it a default of `null`.
|
|
|
|
### Remember me (pre-ticked by default)
|
|
|
|
```csharp
|
|
new Checkbox(
|
|
id: "remember",
|
|
label: "Remember me",
|
|
name: "rememberMe",
|
|
checked: true)
|
|
```
|
|
|
|
### Multiple checkboxes in a preferences form
|
|
|
|
```csharp
|
|
new Checkbox(id: "email-alerts", label: "Email alerts", name: "emailAlerts")
|
|
new Checkbox(id: "sms-alerts", label: "SMS alerts", name: "smsAlerts")
|
|
new Checkbox(id: "weekly-summary", label: "Weekly summary", name: "weeklySummary")
|
|
```
|
|
|
|
Server-side:
|
|
|
|
```csharp
|
|
public record Command(
|
|
[property: FromForm] string? EmailAlerts = null,
|
|
[property: FromForm] string? SmsAlerts = null,
|
|
[property: FromForm] string? WeeklySummary = null
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## How it works
|
|
|
|
Checkbox renders a native `<input type="checkbox">` styled with `accent-primary` so the checkmark colour matches your theme's primary colour. The label is a separate `<label for="{id}">` element — clicking anywhere on the label text toggles the checkbox.
|
|
|
|
---
|
|
|
|
## Complete page example
|
|
|
|
**`Templates/PreferencesPage.htmx`**
|
|
```html
|
|
<div class="max-w-md mx-auto py-10">
|
|
<h1 class="text-2xl font-bold mb-6">Preferences</h1>
|
|
<form method="post" action="/preferences">
|
|
$$AntiforgeryToken$$
|
|
<div class="space-y-4 mb-6">
|
|
$$NewsletterCheck$$
|
|
$$MarketingCheck$$
|
|
$$RememberCheck$$
|
|
</div>
|
|
$$SaveBtn$$
|
|
</form>
|
|
$$SuccessAlert$$
|
|
</div>
|
|
```
|
|
|
|
**`Templates/PreferencesPage.htmx.cs`**
|
|
```csharp
|
|
namespace Htmx.ApiDemo.Templates;
|
|
|
|
public sealed class PreferencesPage : PreferencesPageBase
|
|
{
|
|
private readonly IHtmxComponent _newsletter;
|
|
private readonly IHtmxComponent _marketing;
|
|
private readonly IHtmxComponent _remember;
|
|
private readonly IHtmxComponent _save;
|
|
private readonly IHtmxComponent _success;
|
|
private readonly byte[] _afToken;
|
|
|
|
public PreferencesPage(
|
|
IAntiforgery af,
|
|
HttpContext ctx,
|
|
UserPrefs? prefs = null,
|
|
bool saved = false)
|
|
{
|
|
var tokens = af.GetAndStoreTokens(ctx);
|
|
_afToken = $"""<input type="hidden" name="{tokens.FormFieldName}" value="{tokens.RequestToken}">""".ToUtf8Bytes();
|
|
|
|
_newsletter = new Components.Checkbox(
|
|
id: "newsletter", label: "Receive newsletter",
|
|
name: "newsletter", @checked: prefs?.Newsletter ?? false);
|
|
_marketing = new Components.Checkbox(
|
|
id: "marketing", label: "Receive marketing emails",
|
|
name: "marketing", @checked: prefs?.Marketing ?? false);
|
|
_remember = new Components.Checkbox(
|
|
id: "remember", label: "Keep me signed in",
|
|
name: "remember", @checked: prefs?.Remember ?? false);
|
|
_save = new Components.Button("Save preferences", type: "submit");
|
|
_success = saved
|
|
? new Components.Alert(title: "Preferences saved.")
|
|
: HtmxEmpty.Instance;
|
|
}
|
|
|
|
protected override void RenderAntiforgeryToken(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_afToken);
|
|
protected override void RenderNewsletterCheck(HtmxRenderContext ctx) => _newsletter.Render(ctx.Next());
|
|
protected override void RenderMarketingCheck(HtmxRenderContext ctx) => _marketing.Render(ctx.Next());
|
|
protected override void RenderRememberCheck(HtmxRenderContext ctx) => _remember.Render(ctx.Next());
|
|
protected override void RenderSaveBtn(HtmxRenderContext ctx) => _save.Render(ctx.Next());
|
|
protected override void RenderSuccessAlert(HtmxRenderContext ctx) => _success.Render(ctx.Next());
|
|
}
|
|
```
|
|
|
|
**POST handler**
|
|
```csharp
|
|
[Handler]
|
|
[MapPost("/preferences")]
|
|
public static partial class PostPreferencesHandler
|
|
{
|
|
public record Command(
|
|
[property: FromForm] string? Newsletter = null,
|
|
[property: FromForm] string? Marketing = null,
|
|
[property: FromForm] string? Remember = null);
|
|
|
|
private static Task<IResult> HandleAsync(
|
|
[AsParameters] Command cmd, HttpContext ctx, IAntiforgery af, CancellationToken ct)
|
|
{
|
|
var prefs = new UserPrefs(
|
|
Newsletter: cmd.Newsletter != null,
|
|
Marketing: cmd.Marketing != null,
|
|
Remember: cmd.Remember != null);
|
|
// Persist prefs…
|
|
return ctx.WriteHtmxPage(new PreferencesPage(af, ctx, prefs, saved: true), title: "Preferences");
|
|
}
|
|
}
|
|
|
|
public record UserPrefs(bool Newsletter, bool Marketing, bool Remember);
|
|
```
|
|
|
|
**`AppJsonSerializerContext.cs`**
|
|
```csharp
|
|
[JsonSerializable(typeof(PostPreferencesHandler.Command), TypeInfoPropertyName = "PreferencesCommand")]
|
|
```
|