DFormFile
DFormFile - A type-safe wrapper around Bootstrap Vue Next’s BFormFile component. A file picker with a Browse button, the chosen file name, and a drag-and-drop zone, styled like the theme’s text inputs (same height, border, focus ring and crimson invalid state). v-model is a File for a single file, a File[] with multiple (or directory), and null when nothing is chosen (or [] for a cleared multiple model).
Use it instead of hand-building a btn label around a hidden <input type="file">. The Browse button is a real <button>, so it is in the Tab order and opens the picker on Enter or Space.
label-for is required to label it. Give the component an id and pass the same value to DFormGroup’s label-for. Without label-for, DFormGroup renders a <fieldset> with a <legend>, which does not name the button: its accessible name is then just “Browse”. With no visible label, use aria-label.
Live Examples
Single File
Selected: none
Multiple Files with File Names
Drop Zone
Drag files onto the control, or click it to browse.
Invalid State
Sizes and Disabled
Props
All props pass through to BFormFile.
| Name Click to sort ascending | Type | Required Click to sort ascending | Default | Description |
|---|---|---|---|---|
modelValue | File | readonly File[] | null | No | null | The chosen file(s). Use v-model. An array when multiple or directory is set. Setting it to null (or [] with multiple/directory) clears the selection and the native input. |
accept | string | readonly string[] | No | '' | Accepted types, e.g. "image/*,.pdf". Also filters dropped files. |
multiple | boolean | No | false | Allow more than one file. |
directory | boolean | No | false | Pick a whole directory (webkitdirectory). Implies multiple. |
capture | 'user' | 'environment' | No | - | Ask a phone to use its camera. |
id | string | No | generated | Set on the Browse button; pass the same value to DFormGroup's label-for. |
name | string | No | - | Name of the hidden native input, for a plain form submit. |
form | string | No | - | The id of the form the native input belongs to. |
placeholder | string | No | 'No file chosen' | Text shown while nothing is chosen. |
browseText | string | No | 'Browse' | The Browse button label. |
dropPlaceholder | string | No | 'Drop files here...' | Text on the overlay while files are dragged over the control. |
showFileNames | boolean | No | false | Also show the chosen file name(s) below the control (rendered by the file-name slot when given). |
fileNameFormatter | (files: readonly File[]) => string | No | - | Formats the file-name text. Default: the name, or "N files selected". |
noButton | boolean | No | false | Hide the Browse button. The control stays clickable, but has no focusable element. |
noDrop | boolean | No | false | Turn off drag and drop. Drops are off while the control is disabled, whatever noDrop says. |
plain | boolean | No | false | Render the native file input (with .form-control) instead of the custom control. |
size | 'sm' | 'md' | 'lg' | No | - | Control size, matching DFormInput. |
state | boolean | null | No | null | false shows the invalid state, true the valid state. Not inherited from DFormGroup's state; see Validation. |
disabled | boolean | No | false | Disable the control. A disabled control (or one inside a disabled DFormGroup or fieldset) also ignores dropped files. |
required | boolean | No | false | Mark the native input required. Use it with plain only; see Validation. |
autofocus | boolean | No | false | Focus the Browse button on mount. |
label | string | No | '' | BFormFile's own label above the control. Prefer DFormGroup's label in forms. |
ariaLabel | string | No | - | Accessible name for the Browse button when there is no visible label. |
ariaLabelledby | string | No | - | Id(s) of the element(s) naming the Browse button. |
labelClass | ClassValue | No | - | Class(es) for BFormFile's own label. |
Events
| Name Click to sort ascending | Parameters | Description |
|---|---|---|
update:modelValue | | The selection changed (picked, dropped or reset). |
change | | After a selection. In the custom control it is a CustomEvent whose files property (and detail.files) holds the File[]; with plain it is the native change event. |
Slots
All slots are forwarded with their slot props.
| Name Click to sort ascending | Description | Scoped Props |
|---|---|---|
file-name | Replaces the file-name text inside the control, and the list below it when showFileNames is set. | - |
placeholder | Content shown while nothing is chosen. | - |
drop-placeholder | Content of the drag overlay. | - |
label | Content of BFormFile's own label (with the label prop). | - |
Validation
Pass state to DFormFile itself. false gives the control the crimson invalid border and icon, and shows a sibling DFormInvalidFeedback (and true a sibling DFormValidFeedback), as with DFormInput:
<DFormFile id="contract" v-model="contract" :state="contract ? null : false" />
<DFormInvalidFeedback>Please choose the signed contract.</DFormInvalidFeedback>
A DFormGroup’s state does not reach DFormFile, unlike DFormInput. Bootstrap Vue Next’s BFormFile does not read the group’s state (or its disabled), and the group passes it down through an injection key that bootstrap-vue-next does not export, so the wrapper cannot read it either without depending on a private name. The control’s own state is the one that matters: it colours the control and shows the feedback beside it, including a DFormGroup’s own invalid-feedback (the group renders it after the control). Set the group’s state as well, as in the Invalid State example, only for what the group itself carries: the is-invalid class and aria-invalid on its <fieldset>. disabled does reach the control: a DFormGroup always renders a <fieldset> (label-for only swaps its <legend> for a <label>), so a disabled group disables the Browse button and the native input, the theme greys the control, and dropped files are ignored.
Avoid required on the custom control. It lands on the hidden native input: the browser’s own validation blocks a plain form submit and focuses the invisible input, so the browser’s message is lost. Validate on the server (or in your submit handler) and show the result with state and a feedback message. required works as expected with plain.
Where attributes land
In the custom control, class and style go on the root element, title on the drop zone, and everything else on the hidden native input (tabindex="-1", aria-hidden): name, data-* and listeners such as @focus and @blur. So @focus/@blur do not fire in normal use (the hidden input is out of the Tab order and only the browser’s own required validation focuses it), and aria-describedby on DFormFile does not describe the Browse button. Run blur-style validation on @change or @update:modelValue instead. With plain, every attribute goes on the native input, which is the focusable control.
Methods
Through a template ref: reset() clears the selection, the native input and the model; focus() and blur() act on the Browse button; element is the Browse button (the native input with plain).
Setting v-model to null (or [] with multiple/directory) clears it the same way: the wrapper empties the native input when the model changes to a cleared value, because Bootstrap Vue Next’s BFormFile on its own clears the file name but leaves the files in the hidden native input (and, for [], in the plain input), where a plain form submit (or new FormData(form)) would still send them. It does not emit another update:modelValue.
Slots
This component forwards all slots dynamically from the underlying Bootstrap Vue Next component.
Bootstrap Vue Next Wrapper
This is a lightweight type-safe wrapper around the corresponding Bootstrap Vue Next component. It provides API stability and forwards all props, events, and slots.
For complete API documentation (props, events, methods), refer to the Bootstrap Vue Next BFormFile documentation .