OWL
inputs
File Input
Odoo 19 OWL component — File Input (core)
Live preview
Interactive
Source excerpt
web/static/src/core/file_input/file_input.js
import { Component, onMounted, useRef, useState } from "@odoo/owl";
import { useFileUploader } from "@web/core/utils/files";
/**
* Custom file input
*
* Component representing a customized input of type file. It takes a sub-template
* in its default t-slot and uses it as the trigger to open the file upload
* prompt.
* @extends Component
*
* Props:
* @param {string} [props.acceptedFileExtensions='*'] Comma-separated
* list of authorized file extensions (default to all).
* @param {string} [props.route='/web/binary/upload'] Route called when
* a file is uploaded in the input.
* @param {string} [props.resId]
* @param {string} [props.resModel]
* @param {string} [props.multiUpload=false] Whether the input should allow
* to upload multiple files at once.
*/
export class FileInput extends Component {
static template = "web.FileInput";
static defaultProps = {
acceptedFileExtensions: "*",
hidden: false,
multiUpload: false,
onUpload: () => {},
route: "/web/binary/upload_attachment",
beforeOpen: async () => true,
};
static props = {
acceptedFileExtensions: { type: String, optional: true },
autoOpen: { type: Boolean, optional: true },
hidden: { type: Boolean, optional: true },
multiUpload: { type: Boolean, optional: true },
onUpload: { type: Function, optional: true },
beforeOpen: { type: Function, optional: true },
resId: { type: Number, optional: true },
resModel: { type: String, optional: true },
route: { type: String, optional: true },
"*": true,
};
setup() {
this.uploadFiles = useFileUploader();
this.fileInputRef = useRef("file-input");
this.state = useState({
// Disables upload button if currently uploading.
isDisable: false,
});
onMounted(() => {
if (this.props.autoOpen) {
this.onTriggerClicked();
}
});
}
get httpParams() {
const { resId, resModel } = this.props;
const params = {
csrf_token: odoo.csrf_token,
ufile: [...this.fileInputRef.el.files],
};
if (resModel) {
params.model = resModel;
}
if (resId !== undefined) {
params.id = resId;
}
return params;
}
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* Upload an attachment to the given route with the given parameters:
* - ufile: list of files contained in the file input
* - csrf_token: CSRF token provided by the odoo global object
* - resModel: a specific model which will be given when creating the attachment
* - resId: the id of the resModel target instance
*/
async onFileInputChange() {
this.state.isDisable = true;
const httpParams = this.httpParams;
if (this.props.onWillUploadFiles) {
try {
const files = await this.props.onWillUploadFiles(httpParams.ufile);
httpParams.ufile = files;
} catch (e) {
this.state.isDisable = false;
throw e;
}
}
const parsedFileData = await this.uploadFiles(this.props.route, httpParams);
if (parsedFileData) {
// When calling onUpload, also pass the files to allow to get data like their names
this.props.onUpload(
parsedFileData,
this.fileInputRef.el ? this.fileInputRef.el.files : []
);
// Because the input would not trigger this method if the same file name is uploaded,
// we must clear the value after handling the upload
this.fileInputRef.el.value = null;
}
this.state.isDisable = false;
}
/**
* Redirect clicks from the trigger element to the input.
*/
async onTriggerClicked() {
if (await this.props.beforeOpen()) {
this.fileInputRef.el.click();
}
}
}
Registry / API
- Registry name
FileInput- Category
—- Module
web- Slug
file-input- Nav group
inputs