wiki:UZ

UZ - generic file uploading component

TL;DR

git clone https://github.com/js29a/uz.git

or

grab source:/uz/src/UploadZone.vue and source:/uz/src/UploadTest.vue

demo is available at https://vite.js29a.usermd.net/#/0

Aim of this article

In this article I'm about to demonstrate how to create and use generic file uploader component. You can use it not only with bare Vue-3 but also with Quasar, Vuetify or other Vue-3 toolkit. This article describes only browser-side concerns. You need to provide server side by you own.

The repository is also mirrored on GitHub.

Prerequisites

To use code covered by this wiki page you need to have following skills:

  • basic Vue-3 knowledge (especially SFC with composition API),
  • basic knowledge of TypeScript,
  • very basic POST knowledge,
  • rudimental knowlegde of jQuery ajax command.

Black-hole PHP POST acceptor script provided for faster setup: source:/uz/php/upload.php.

General info

Described component is based on a simple state machine. It has no UI by itself so you need to provide some UI on your own. To accomplish this not only component instantation is needed but there is also need to fill its slots. The component has several config options from which actually only one needs to be provided (i.e. target upload URL). Other options control component behavior but they will be explained later. After providing target upload URL there is need to fill component slots by your own UI. Here I will describe generic browser UI only. If you are familiar with e.g. Quasar you can implement the UI on your own.

In case of doubt please refer to source:/uz/src/UploadTest.vue file. It's complex because it demonstrates all the features. You'll probably use only some of them. Feel free to experiment.

Basic component usage

The first thing you need to do is to import the component and create an instance of it. Place the following line in your code - be careful to specifiy correct relative component path:

import UploadZone from './UploadZone.vue';

Then at your template code instantiate it. You will have to specify correct target upload URL. Endpoint specified here should handle POST requests.

<component :is='UploadZone' target='http://...'>
</component>

As you see nothing will appear in browser. Why? You need to provide some UI. To remain generic the component has no UI by itself. This allows it to be extremely flexible. You need to use slots and provide some CSS styles. To remain concise this step is demonstrated in the repository (source:/uz/src/UploadTest.vue). After creating the UI and navigating to proper URL you should see the uploader.

In general there are two control options - using slots or to mix slots with control outside of the component. File source:/uz/src/UploadTest.vue demonstrates both of them.

Component properties

target

Destination URL. It should handle POST requests. Mandatory.

max-jobs

Maximum number of concurrent jobs. Optional. Defaults to 3.

auto-start

Start automatically after adding files, i.e. without wait to add more files. Optional. Defaults to false.

auto-reset

Automatically back to idle state after uploading given files. Optional. Defaults to false.

keep-going

Do not abort on error(s) - upload all files that can be uploaded. Optional. Defaults to false.

Slots

Common slot properties

  • abort - callback function for aborting upload,
  • current - files that are currently uploaded,
  • error - error value - raw jQuery response,
  • errors - error vector, used when keep-going is set,
  • pick - callback that launches standard file picker,
  • progress - vector of results of files upload - parsed POST response,
  • queue - vector of files that are waiting for upload,
  • reset - callback function that resets component to idle state,
  • result - vector of parsed POST responses,
  • start - callback function that starts file uploading.

Provided slots

slot name props when used
idle pick nothing has to be done
hover (no props) component is hovered with files - drop is possible
wait start, reset, queue ready for upload
uploading progress, current, queue, errors, abort upload is pending
done results, reset upload is done
error error, reset an error occured
aborted result, reset upload has been aborted
with-errors result, errors, reset upload completed with errors

Exposed items

item purpose kind
pick launches standard file picker callback no args
reset resets to idle state callback no args
start begin files upload callback no args
abort abort pending files upload callback no args
can_pick is file picking allowed? computed boolean
can_start is upload start allowed? computed boolean
can_abort is upload abort allowed? computed boolean
can_reset is component reset allowed? computed boolean

Emitted events

Component state events

  • update:canPick(flag: boolean) - is file picking allowed,
  • update:canReset(flag: boolean) - is component reset allowed,
  • update:canStart(flag: boolean) - is upload start allowed,
  • update:canAbort(flag: boolean) - is upload abort allowed.

Other events

(to be written)

Other things

This component is implemented using Finite State Machine (Moore type) technique. It has eight states (idle, hover, wait, uploading, done, error, with_errors and aborted). It uses jQuery as underlying layer because it is the most common way to do REST requests. Rationale to implement it was need of specifying how many files could be uploaded at one time. The keynote was to not implement UI inside the component but relying to do such thing by user of this component.

Conclusion

The aim was rather to demonstrate some idea than to create universal piece of code. The idea was to demonstrate how to separate totally underlying controller layer from the UI. I hope this idea could be useful for someone.

Thanks for reading!


Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Last modified 2 years ago Last modified on 2022.10.06 19:57:29
Note: See TracWiki for help on using the wiki.