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.
Anatomy
Section titled “Anatomy”| 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:
- The page renders the component: it issues a token and puts it into the view.
- A click sends
_token,_actionand the input to the endpoint. - The endpoint verifies the token, finds the component, checks the permission of the action and validates the input.
- The handler changes data and renders the component again (with a fresh token).
- htmx swaps the fragment into the page;
HX-Triggerevents show toasts or refresh other parts.
Pages of this chapter
Section titled “Pages of this chapter”| 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 |
Components of Anvil
Section titled “Components of Anvil”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 |
Rules in short
Section titled “Rules in short”- 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
styleattributes (CSP). - Actions that change data run in a transaction and are audited.