---
title: "FileUploader"
description: "A controlled file picker with drag and drop and a file list."
category: Form
status: beta
since: 0.3.4
tags: [upload, file, form]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
`accept` limits the types and `max` the total count.
::::TuffDemoWrapper{demo="FileUploaderFileUploaderDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'

  const files = ref([])
  </script>

  <template>
    <TxFileUploader v-model="files" accept=".pdf,.png,.jpg" :max="5" />
  </template>
---
::::

### Upload After Selection
`add` carries only the newly added files; `change` and `update:modelValue` carry the full list.

```vue
<script setup lang="ts">
import type { FileUploaderFile } from '@talex-touch/tuffex/file-uploader'
import { ref } from 'vue'

const files = ref<FileUploaderFile[]>([])

async function uploadAdded(added: FileUploaderFile[]) {
  await Promise.all(added.map(item => uploadFile(item.file)))
}
</script>

<template>
  <TxFileUploader v-model="files" accept="image/*" :max="3" @add="uploadAdded" />
</template>
```

### Imperative Picker
`pick()` opens the native picker, unless disabled.

```vue
<script setup lang="ts">
const uploader = ref<{ pick: () => void }>()
</script>

<template>
  <TxFileUploader ref="uploader" v-model="files" />
  <TxButton @click="uploader?.pick()">Browse</TxButton>
</template>
```

### Best Practices

- Upload `FileUploaderFile.file` as the payload; the other fields only drive the UI.
- Revalidate count, size, MIME, and content on the server; `accept` and `max` are UI constraints only.
- Run upload side effects on `add`; listen to `change` when you need the full list.
- Generated `id`s are valid only for the current UI session; don't persist them.
- Set `allowDrop=false` in compact forms where an accidental drop is costly.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `modelValue` | `FileUploaderFile[]` | `[]` | The selected files (controlled). |
| `multiple` | `boolean` | `true` | Passed to the native input. |
| `accept` | `string` | `'*/*'` | Accepted file types; passed to the native input and applied the same way to dropped files. |
| `disabled` | `boolean` | `false` | Blocks browsing, removing, and dropping. |
| `max` | `number` | `10` | Maximum total number of selected files. |
| `showSize` | `boolean` | `true` | Shows file sizes in the list. |
| `allowDrop` | `boolean` | `true` | Lets files be added by dropping. |
| `buttonText` | `string` | `'Choose files'` | Browse button text. |
| `dropText` | `string` | `'Drop files here'` | Primary drop-zone text. |
| `hintText` | `string` | `'or click to browse'` | Drop-zone hint text. |

### Events

| Event | Payload | Description |
|------|---------|-------------|
| `update:modelValue` | `FileUploaderFile[]` | The full list after an add or remove. |
| `change` | `FileUploaderFile[]` | Fires together with `update:modelValue`. |
| `add` | `FileUploaderFile[]` | The files accepted in this addition. |
| `remove` | `{ id: string, value: FileUploaderFile[] }` | The removed id and the remaining list. |

### Exposed Methods

| Name | Type | Description |
|------|-----------|-------------|
| `pick` | `() => void` | Opens the native file picker unless disabled. |

### Types

`FileUploaderFile`, one entry of the list:

| Field | Type | Description |
|------|------|-------------|
| `id` | `string` | Generated unique id, used as the list key and remove payload. |
| `name` | `string` | Original file name. |
| `size` | `number` | File size in bytes. |
| `type` | `string` | MIME type. |
| `file` | `File` | The browser `File` object. |

## Overview

- The drop zone is a native `<button type="button">` that calls `pick()`; a hidden `<input type="file">` takes `multiple`, `accept`, and `disabled`.
- The native input is cleared after each pick, so the same file can be picked again.
- With `multiple`, additions are capped at the remaining capacity `max - modelValue.length`, and nothing is emitted at zero; a single uploader replaces its file.
- An addition emits `add`, `update:modelValue`, then `change`; a removal emits `remove`, `update:modelValue`, then `change`.
- Drops are ignored when `allowDrop=false` or `disabled`; the root carries `is-dragging` during a drag.
- With `showSize`, sizes render as `B`, `KB`, or `MB`.

## Technologies

- Source: `packages/tuffex/packages/components/src/file-uploader/`.

<TuffDocSourceLink />
