Skip to content

Detail page

The detail page (/admin/<slug>/{uuid}) shows one record. It needs <slug>.view and the policy of the record; a record outside the tenant or scopeQuery() answers 404.

From top to bottom:

  1. Header: the record title (recordTitle()), the label of the resource as subtitle, and the buttons: edit, delete and the actions the user may run.
  2. Form, read-only: the schema of form() in the operation view – same layouts, each field with its read-only display. Fields and layouts with hiddenOn('view') are left out.
  3. Related records: one section (or tab) per relation, see Related records.
  4. Workflow components and own components, see below.
  5. Attachments, if enabled.
  6. History, for users with <slug>.history, see History.

The breadcrumbs lead back to the list.

protected bool $attachments = true;

The detail page then shows the files of the record:

  • Users who may see the record see and download them.
  • Users who may update it (permission <slug>.update and policy) upload and delete them; up to 10 files per upload.
  • Files are checked like every upload (type and content, size, virus scanner) and belong to the resource class (fileOwner()).
  • Deleting the record deletes its files (not with soft deletes).

Details: Files. One file per field instead: FileUpload.

detailComponents() adds own sections, e.g. the tokens of an API client or a checklist:

public function detailComponents(): array
{
return ['checklist' => new ChecklistComponent($this)];
}

A component implements Anvil\Resource\RecordComponent:

Method Purpose
render(ComponentClaims $claims): string the HTML of the section; escape every value
actions(ComponentClaims $claims): array the ComponentActions it accepts through the component endpoint
  • The key is the component kind ([a-z][a-z0-9-]*), not collection, form or attachments. Kinds starting with workflow- are used by the components of workflows, which come first.
  • The record comes from the token ($claims->record), never from the input. render() is called after the view permission of the record was checked; actions check their permission (ComponentAction) and the policy of the record themselves.
  • An action answers with ComponentResponse::html($this->render(...)) to replace the section, e.g. hx-target="#my-section" hx-swap="outerHTML".

Writing components: Components.

  • Edit (/{uuid}/edit) shows the form in the operation edit; it needs canUpdate() (permission, policy, not locked by a workflow). Saving leads back to the detail page.
  • Create (/create) needs canCreate(); saving leads to the detail page of the new record. From a relation section it is opened with the parent and leads back to the parent.