summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorJulien Mougenot <jum@odoo.com>2019-11-22 11:37:09 +0000
committerJulien Mougenot <jum@odoo.com>2020-01-06 14:37:16 +0000
commit3c5194a00b3c0525dfd84552233e9c8f85a150f4 (patch)
treeaa2057962f6aefe00418de4c037f74010c7eb879 /addons/web/static/src
parent34bbdd88c0bc354b76b254bb78c4eb786f3d08c0 (diff)
[ADD] web: Custom File Input
New component: the custom file input. Its purpose is to define a input of type file with a custom trigger (button, link, etc.). Its construction is the following: - attributes: behaviour of the actual input (route to call, multifile, allowed extensions etc.) - inner template: the trigger that will fire the upload prompt when clicked Once a file has been uploaded, the component will emit a 'uploaded' custom event containing the files. closes odoo/odoo#38423 Related: odoo/enterprise#6031 Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/components/custom_file_input.js88
-rw-r--r--addons/web/static/src/xml/base.xml15
2 files changed, 103 insertions, 0 deletions
diff --git a/addons/web/static/src/js/components/custom_file_input.js b/addons/web/static/src/js/components/custom_file_input.js
new file mode 100644
index 00000000000..eb9c4267cfc
--- /dev/null
+++ b/addons/web/static/src/js/components/custom_file_input.js
@@ -0,0 +1,88 @@
+odoo.define('web.CustomFileInput', function (require) {
+ "use strict";
+
+ const { Component, hooks } = owl;
+ const { useRef } = hooks;
+
+ /**
+ * 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
+ */
+ class CustomFileInput extends Component {
+ /**
+ * @param {Object} [props]
+ * @param {string} [props.accepted_file_extensions='*'] Comma-separated
+ * list of authorized file extensions (default to all).
+ * @param {string} [props.action='/web/binary/upload'] Route called when
+ * a file is uploaded in the input.
+ * @param {string} [props.id]
+ * @param {string} [props.model]
+ * @param {string} [props.multi_upload=false] Whether the input should allow
+ * to upload multiple files at once.
+ */
+ constructor() {
+ super(...arguments);
+
+ this.fileInputRef = useRef('file-input');
+ }
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Upload an attachment to the given action with the given parameters:
+ * - ufile: list of files contained in the file input
+ * - csrf_token: CSRF token provided by the odoo global object
+ * - model: a specific model which will be given when creating the attachment
+ * - id: the id of the model target instance
+ * @private
+ */
+ async _onFileInputChange() {
+ const { action, model, id } = this.props;
+ const params = {
+ csrf_token: odoo.csrf_token,
+ ufile: [...this.fileInputRef.el.files],
+ };
+ if (model) {
+ params.model = model;
+ }
+ if (id) {
+ params.id = id;
+ }
+ const fileData = await this.env.services.httpRequest(action, params, 'text');
+ const parsedFileData = JSON.parse(fileData);
+ if (parsedFileData.error) {
+ throw new Error(parsedFileData.error);
+ }
+ this.trigger('uploaded', { files: parsedFileData });
+ }
+
+ /**
+ * Redirect clicks from the trigger element to the input.
+ * @private
+ */
+ _onTriggerClicked() {
+ this.fileInputRef.el.click();
+ }
+ }
+ CustomFileInput.defaultProps = {
+ accepted_file_extensions: '*',
+ action: '/web/binary/upload',
+ multi_upload: false,
+ };
+ CustomFileInput.props = {
+ accepted_file_extensions: { type: String, optional: 1 },
+ action: { type: String, optional: 1 },
+ id: { type: Number, optional: 1 },
+ model: { type: String, optional: 1 },
+ multi_upload: { type: Boolean, optional: 1 },
+ };
+ CustomFileInput.template = 'CustomFileInput';
+
+ return CustomFileInput;
+});
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 961c11cdc90..5470a721805 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -3,6 +3,21 @@
<!-- Owl Templates -->
+<t t-name="CustomFileInput" owl="1">
+ <span class="o_file_input" aria-atomic="true">
+ <span class="o_file_input_trigger" t-on-click.prevent="_onTriggerClicked">
+ <t t-slot="default">
+ <button class="btn btn-primary">Choose File</button>
+ </t>
+ </span>
+ <input type="file" name="ufile" class="o_input_file d-none"
+ t-att="{multiple: props.multi_upload, accept: props.accepted_file_extensions}"
+ t-ref="file-input"
+ t-on-change="_onFileInputChange"
+ />
+ </span>
+</t>
+
<t t-name="DialogButton.tooltip" owl="1">
<div class="oe_tooltip_string" role="tooltip">
<div class="tooltip-inner">