AppFileAttachment
A compact browse row that swaps to a thumbnail (or file-type icon) + filename/size — one file or many.
<app-file-attachment name="doc" label="Ticket attachment" /><app-file-attachment> attaches a file to something — a ticket, a message, a comment — where the file's name and size matter more than a big preview. It shows a slim browse row that swaps to a preview (an image thumbnail, or a file-type icon for PDFs and other documents) plus the filename and size once a file is chosen (× to remove). Add multiple="true" to let several files stack in a list, each removable on its own.
Its look comes entirely from the shared @webority/theme, so the Razor <app-file-attachment> and the React <AppFileAttachment> render identically on every Webority surface. Never hand-roll a raw <input type="file">.
Playground
Every meaningful attribute, live. Each change re-renders the real tag helper on the server; pick or reject a file in the row below to see the same client-side thumbnail/icon swap and validation error React shows.
accept or over max-size-mb and the field shows its own rejection message below the row — the same .field-error spot the error attribute uses. The two never show at once; a fresh pick clears whichever is showing.The attach row
Empty, the field is a compact row with a browse affordance. Pick a file to see it swap to a thumbnail + name + size.
Show code
<app-file-attachment name="ticketAttachment" label="Ticket attachment" optional="true" />
AppFilePicker instead.Accepted types
Narrow the accepted types to the formats you handle; the field enforces type and size before it reports the choice, and a rejected file shows an inline message.
Show code
<app-file-attachment name="ticketAttachment" label="Ticket attachment" accept="image/png,image/jpeg" optional="true" />
Multiple & file types
Widen accept beyond images and the row accepts any type — a non-image file shows a file-type icon instead of a thumbnail. Add multiple="true" and picked files stack in a list, each with its own × to remove.
Show code
<app-file-attachment name="attachments" label="Attachments" multiple="true" accept="image/png,image/jpeg,application/pdf" optional="true" />
Optional & errors
Mark the field optional to add an “(optional)” hint beside the label, and pass an error to surface a submit-time problem below the row in the field's error style.
Show code
<app-file-attachment name="ticketAttachment" label="Ticket attachment" optional="true" /> <app-file-attachment name="photo" label="Photo" error="File is required" />
When to use
Use it when
- A file is attached to a record — a ticket, a message, a comment — as evidence.
- The filename and size matter more than seeing the picture large.
- You want type + size validation and preview handling done for you in a compact row.
Reach for something else when
- The image is the star and the user should see it large. → AppFilePicker
- The upload is a round avatar or a company logo. → AppLogoPicker
- It is a plain text or number field, not a file. → AppInput
- You hand-roll a raw <input type="file"> with custom markup. → AppFileAttachment
Best practices
Every option
The whole surface of the component, one cell per case. The tag helper has no value attribute — a picked-file preview only exists after a real client-side pick (webority-ui.js), so the preview/size/multiple groups below hand-write that same markup as a static illustration; every other group renders the real <app-file-attachment>.
preview — image thumbnail vs file-type icon
picked: image — big preview, single mode (static illustration)
picked: non-image — compact row, file-text icon (static illustration)
existing { url, name }, accept=image-only — treated as an image (static illustration)
existing { url, name }, accept=mixed — judged by name, file-text icon (static illustration)
size / meta line
a picked file — size shown (static illustration)
an already-attached file — no size line (size unknown) (static illustration)
multiple — stacked list, each with its own remove
multiple, mixed image + non-image files (static illustration)
states
(default) — empty, requiredoptional="true" — emptyerror="File is required" — no valueerror — alongside a picked file (static illustration)
accept — every hint variant
accept="image/png,image/jpeg,image/webp"
accept="image/png,image/jpeg"
accept="image/png,image/jpeg,application/pdf"
accept="application/pdf"
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| name | string | — | Form field name for the posted file input. |
| label | string | Attachment | Field label shown above the row. |
| accept | string | image/png,image/jpeg,image/webp | Comma-separated MIME/extension allowlist. Widen it (e.g. image/*,application/pdf) to accept non-image files. An empty value accepts any file type, and the hint then names no types. |
| multiple | bool | false | Accept several files at once — they stack in a list, each removable on its own. |
| optional | bool | false | Adds an “(optional)” hint beside the label. |
| error | string | — | Error message shown below the row, in the field-error style. |
| max-size-mb | int | 5 | Maximum accepted file size in MB (React maxSizeMb). Unset means 5. 0 or less means no size limit, and the hint then names no size. |
| validate | bool | true | Check each pick against accept and max-size-mb in the browser and show the field's own message for a rejected file. Set false when the page validates the files and shows its own message through error, so one problem never gets two messages. The limits still set the picker filter and the hint. |
| value | — | — | React-only. The tag helper has no value input — a picked file only exists as client-side state (webority-ui.js) after the user interacts with the row; there is no way to pre-render an already-attached file from the server. |