Skip to content

Responses

Anvil\Endpoint\ComponentResponse:

Factory Status Effect in the browser
ComponentResponse::html($html) 200 htmx swaps the fragment (hx-target, hx-swap)
ComponentResponse::empty() 204 nothing is swapped; combine with events, or use hx-swap="none"
ComponentResponse::redirect($path) 200 navigates to the path like a boosted link (HX-Location, target body)
ComponentResponse::download($path) 200 the browser loads the file (HX-Redirect); the page stays
->withEvent($name, $payload) – adds an event to HX-Trigger; can be chained for several events
  • html() expects safe HTML: render a view and escape every value.
  • redirect() and download() only accept paths of the application (starting with one /, no host); anything else throws. Panel::url() returns a full URL, so pass a path, e.g. $resource->path('view', $uuid) or '/' . trim((string) parse_url($this->panel->url('triage'), PHP_URL_PATH), '/').
  • anvil:notify with ['message' => …, 'type' => 'success'|'danger'|'warning'|'info'|'primary'|'secondary'] shows a toast; the message is inserted as text.
  • Every answer has Cache-Control: no-store.
// Swap the component, show a toast
return ComponentResponse::html($this->render($request->claims))
->withEvent('anvil:notify', ['message' => 'Saved', 'type' => 'success']);
// Nothing to swap: only tell other parts of the page
return ComponentResponse::empty()->withEvent('app:tickets');
// After creating: go to the new record
return ComponentResponse::redirect($resource->path('view', $uuid));
// A generated file, served by a route of your application
return ComponentResponse::download('/admin/reports/' . $report->uuid . '/download');

The download URL must check the permission itself; the endpoint only passes it to the browser.

Validation errors, missing permissions and unknown records are thrown as EndpointException, see Actions → Errors. The endpoint turns them into JSON answers that anvil.js shows next to the fields or as a toast.