Skip to content

Components

A component is a server side class that a part of a page talks to: a button marks a ticket as read, a form saves settings, a badge reloads a count. The browser sends the request with htmx to the component endpoint of the panel (POST /<panel>/_anvil); the component answers with an HTML fragment that htmx swaps into the page.

Everything interactive in Anvil works this way: lists (collection), forms (form), attachments, the task inbox, the notification bell, the profile. Your own components use the same pipeline and get the same protection.

How the endpoint checks a request (token, panel, tenant, permission, validation, transaction, audit) is described in Component endpoint. This chapter is about building components.

Part What it does
Component class implements Anvil\Endpoint\Component: actions(ComponentClaims $claims) lists what may be called, each with a permission and validation rules
Registration how the endpoint finds the component by its id: a page (HasComponents), a resource, or the registry
Claims and token ComponentClaims names the component, panel, tenant and optional record; service('componentTokens')->issue($claims) turns them into an encrypted token
View renders the HTML with the token, the endpoint URL and htmx attributes
Handler private method that receives a ComponentRequest and returns a ComponentResponse

The request flow:

  1. The page renders the component: it issues a token and puts it into the view.
  2. A click sends _token, _action and the input to the endpoint.
  3. The endpoint verifies the token, finds the component, checks the permission of the action and validates the input.
  4. The handler changes data and renders the component again (with a fresh token).
  5. htmx swaps the fragment into the page; HX-Trigger events show toasts or refresh other parts.
Page Content
Getting started a complete component: page, component, view and tests
Registration how the endpoint finds a component by its id
Claims and tokens what a token grants: panel, tenant, record, context
Actions permissions, validation, input, transactions, errors
Responses HTML, redirects, downloads, events
Views and htmx token and action in the view, targets, forms with field errors
Alpine.js client behaviour under the strict CSP
Events and refreshing toasts, refreshing other parts, polling
Testing dispatching actions in tests

Your own components work like Anvil’s. Reading one of them is a good start for a component of your own:

Component Class What it does
list Anvil\Resource\Components\CollectionComponent search, filters, sorting, paging, row and bulk actions
form Anvil\Resource\Components\FormComponent create and edit with validation
attachments Anvil\Resource\Components\AttachmentsComponent upload, download and delete files of a record
notification bell Anvil\Notifications\NotificationCenter count with polling, list, mark as read
task inbox Anvil\Tasks\Ui\InboxComponent one action per open task
global search Anvil\Panel\GlobalSearch read-only search over resources
profile Anvil\Access\PasswordComponent, Anvil\Auth\Mfa\MfaComponent password and two-factor set-up of the user
  • Every action has a permission; input without a validation rule is dropped.
  • Records are addressed by UUID; internal ids never reach the browser.
  • The token, not the input, says which panel, tenant and record a request is about.
  • Escape everything you render; no inline scripts or style attributes (CSP).
  • Actions that change data run in a transaction and are audited.