Installation
import { WrFileUpload } from 'ngwr/file-upload';
@Component({ imports: [WrFileUpload] })
export class MyComponent {
protected readonly files = signal<readonly File[] | null>(null);
}Single file
Default mode — last accepted file wins.
<wr-file-upload [(value)]="file" />Multiple files
multiple enables additive selection; maxFiles caps it.
<wr-file-upload [(value)]="files" [multiple]="true" [maxFiles]="5" />Constrained
accept filters by extension or MIME; maxSize enforces a per-file byte cap. Rejected files come through (rejected).
<wr-file-upload
[(value)]="avatar"
accept=".png,.jpg,image/webp"
[maxSize]="2 * 1024 * 1024"
helperText="PNG, JPG or WebP, up to 2 MB"
(rejected)="onRejected($event)"
/>Types
Data shapes used by the inputs and outputs above.
interface WrFileUploadRejection {
file: File;
reason: WrFileUploadRejectionReason;
}
type WrFileUploadRejectionReason = 'type' | 'size' | 'count';| Name | Description | Type | Default |
|---|---|---|---|
WrFileUploadRejection | One rejected file, emitted via (rejected). | interface | — |
filerequired | The rejected File object. | File | — |
reasonrequired | Why it was rejected. | WrFileUploadRejectionReason | — |
WrFileUploadRejectionReason | Rejection cause. | 'type' | 'size' | 'count' | — |
API
| Name | Description | Type | Default |
|---|---|---|---|
multiple | Allow multiple files. Single mode replaces on each add. | boolean | false |
accept | accept attribute — comma-separated MIME types or extensions. | string | '' |
maxSize | Max bytes per file. 0 disables the check. | number | 0 |
maxFiles | Max files (multi mode only). 0 disables the check. | number | 0 |
showList | Render the picked-files list below the zone. | boolean | true |
disabled | Disable interaction. Bound automatically from the field's disabled state when used with [formField]. | boolean | false |
readonly | Refuse changes to the selection while the zone stays focusable and the files still submit. Bound automatically from the field's readonly state when used with [formField]. The zone stops opening the picker, a drop is refused and the per-file remove buttons go inert — but the list stays readable, which is the point. No aria-readonly: the zone is a role="button", and ARIA does not define the state for that role, so aria-disabled would be the only mirror available and it would say the wrong thing. | boolean | false |
pickLabel | Primary call-to-action label. Falls back to fileUpload.browse. | string | null | null |
dropLabel | Secondary instruction below the CTA. Falls back to fileUpload.dropZone. | string | null | null |
dropZoneLabel | Drop-zone host aria-label. Falls back to fileUpload.dropZoneLabel. | string | null | null |
removeFileLabel | Remove-file button aria-label. Falls back to fileUpload.removeFile. | string | null | null |
helperText | Optional helper text shown below the labels (e.g. accepted formats). | string | '' |
value | Selected file(s). Bound by [formField], or two-way via [(value)]. Shape follows multiple: a single File (or null), or a File[] array. | File | readonly File[] | null | null |
(rejected) | Emitted when files are rejected for type / size / count reasons. | readonly WrFileUploadRejection[] | — |
(touch) | Emitted on commit so a bound field can mark itself touched. | void | — |