Contact Form
Fill in the form, attach a file if you like, and send it. Wrong fields show an error next to them. The form posts as multipart/form-data: text fields arrive in $c->input(), the file in $c->file(), and the form comes back re-rendered over SSE.
No base64 overhead. Datastar's
contentType: 'form' modifier submits the nearest <form enctype="multipart/form-data"> as a real multipart POST: files travel as binary, not JSON blobs.Two validation layers. HTML5
required / type="email" / minlength attributes make Datastar call reportValidity() before the request is even sent. The server then re-validates every field independently.$c->file('attachment') returns the parsed upload array (name, type, tmp_name, size) if the upload succeeded, or null if no file was sent or the upload failed.State shared via PHP references. The action and view closures share mutable variables with
use (&$ref). No signals needed: nothing is client-reactive. The SSE block re-render reads the updated values directly via Twig.Success toggled server-side. On clean submission
$submitted becomes true; the re-rendered block switches to the confirmation panel. No page reload, no client branching.Actions
submit
Validates all fields server-side. Mutates shared PHP reference variables on failure or on success, then calls $c->sync() to trigger a block re-render via SSE.
Views
contact-form.html.twig
Form with inline errors and a success panel. Submitted as multipart/form-data via Datastar contentType: form, with the context id in a hidden via_ctx field.