DFormFile

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
No file chosen

Selected: none

Multiple Files with File Names
No photos chosen
Drop Zone

Drag files onto the control, or click it to browse.

Drop files here or choose
Invalid State
No file chosen
Please choose the signed contract.
Sizes and Disabled
Small
Large
Disabled

Props

All props pass through to BFormFile.

Name Click to sort ascendingType Required Click to sort ascendingDefault Description
modelValueFile | readonly File[] | nullNonullThe 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.
acceptstring | readonly string[]No''Accepted types, e.g. "image/*,.pdf". Also filters dropped files.
multiplebooleanNofalseAllow more than one file.
directorybooleanNofalsePick a whole directory (webkitdirectory). Implies multiple.
capture'user' | 'environment'No-Ask a phone to use its camera.
idstringNogeneratedSet on the Browse button; pass the same value to DFormGroup's label-for.
namestringNo-Name of the hidden native input, for a plain form submit.
formstringNo-The id of the form the native input belongs to.
placeholderstringNo'No file chosen'Text shown while nothing is chosen.
browseTextstringNo'Browse'The Browse button label.
dropPlaceholderstringNo'Drop files here...'Text on the overlay while files are dragged over the control.
showFileNamesbooleanNofalseAlso show the chosen file name(s) below the control (rendered by the file-name slot when given).
fileNameFormatter(files: readonly File[]) => stringNo-Formats the file-name text. Default: the name, or "N files selected".
noButtonbooleanNofalseHide the Browse button. The control stays clickable, but has no focusable element.
noDropbooleanNofalseTurn off drag and drop. Drops are off while the control is disabled, whatever noDrop says.
plainbooleanNofalseRender the native file input (with .form-control) instead of the custom control.
size'sm' | 'md' | 'lg'No-Control size, matching DFormInput.
stateboolean | nullNonullfalse shows the invalid state, true the valid state. Not inherited from DFormGroup's state; see Validation.
disabledbooleanNofalseDisable the control. A disabled control (or one inside a disabled DFormGroup or fieldset) also ignores dropped files.
requiredbooleanNofalseMark the native input required. Use it with plain only; see Validation.
autofocusbooleanNofalseFocus the Browse button on mount.
labelstringNo''BFormFile's own label above the control. Prefer DFormGroup's label in forms.
ariaLabelstringNo-Accessible name for the Browse button when there is no visible label.
ariaLabelledbystringNo-Id(s) of the element(s) naming the Browse button.
labelClassClassValueNo-Class(es) for BFormFile's own label.

Events

Name Click to sort ascendingParameters Description
update:modelValueThe selection changed (picked, dropped or reset).
changeAfter 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 ascendingDescription Scoped Props
file-nameReplaces the file-name text inside the control, and the list below it when showFileNames is set.-
placeholderContent shown while nothing is chosen.-
drop-placeholderContent of the drag overlay.-
labelContent 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 .