8.1.4 • Published 5 years ago

vue-transmit v8.1.4

Weekly downloads
639
License
ISC
Repository
github
Last release
5 years ago

Vue-Transmit

npm npm downloads GitHub issues GitHub stars Conventional Commits

A Vue.js drag & drop uploader based on Dropzone.js (~22KB, ~6.5KB gzipped). Many thanks to Matias Meno for paving the way with the original Dropzone.js! Check it out for any of your non-vue projects. 🙌

Features

Vue-Transmit is a fork of Dropzone.js that has been completely rewritten in TypeScript/ES6 for Vue.js. Instead of creating a Vue wrapper component that duplicates and proxies all of the methods and event logic between Dropzone and the component, Vue-Transmit implements them directly from the component. This cuts down on library size and offers a much tighter integration.

Vue-Transmit takes an event-based approach to the upload cycle. Instead of passing callbacks to the component via an options object, use the template event binding syntax (<vue-transmit @event="callback" />). All events strictly conform to kebab-casing, including events proxied off native events (e.g. dragover => @drag-over). This is for uniformity and so events can be easily distinguished.

In order to comply with Vue.js reactivity, an object's properties must be defined up front and be configurable. A special File class has been written (VTransmitFile) to register file objects from uploads reactively, since the native File object's properties are read-only. This class also adds useful information not present in the native File object (dimensions, upload stats, etc.).

  • HTML 5 file uploads
  • Emits upload lifecycle events (accepted, sending, progress, success, etc.)
  • Image thumbnail previews
  • Support for concurrent uploads
  • Completely written in Vue.jsno wrapper components
  • Scoped slots allow for fully customizable styling
  • Written in modern TypeScript/ES6 with modules

* Note: this library uses some built-ins (Array.from) that require a polyfill. All other ESNext language features (arrow fns, for of, etc.) are transpiled with babel.

upload-example

Installation

npm install vue-transmit

Builds

The default build for ESM loaders like webpack is indicated in the module fields of the package. For most setups, importing the lib would like the following:

// ESM
import VueTransmit from "vue-transmit";
// Common.js
const VueTransmit = require("vue-transmit");
// Browser
window.VueTransmit;

// Installation
Vue.use(VueTransmit);
TargetPathMinified
ESMvue-transmit/dist/vue-transmit.esm.jstrue
AMDvue-transmit/dist/vue-transmit.jstrue

Props: <vue-transmit>

PropertyTypeDefault
tagString"div"
uploadAreaClassesArray, Object, Stringnull
uploadAreaAttrsObject{}
uploadAreaListenersObject{}
urlStringundefined
methodString"post"
withCredentialsBooleanfalse
timeoutNumber0
maxConcurrentUploadsNumber2
uploadMultipleBooleanfalse
maxFileSizeNumber256 (in MiB)
paramNameString"file"
createImageThumbnailsBooleantrue
maxThumbnailFileSizeNumber10
thumbnailWidthNumber120
thumbnailHeightNumber120
fileSizeBaseNumber1000
maxFilesNumbernull
paramsObjectdefault
headersObjectdefault
responseTypeString""
clickableBooleantrue
ignoreHiddenFilesBooleantrue
acceptedFileTypesArraydefault
autoProcessQueueBooleantrue
autoQueueBooleantrue
captureStringnull
renameFileFunctionidentity
dictFileTooBigString"File is too big ({{ fileSize }}MiB). Max file size: {{ maxFileSize }}MiB."
dictInvalidFileTypeString"You can't upload files of this type."
dictResponseErrorString"Server responded with {{ statusCode }} code."
dictMaxFilesExceededString"You can not upload any more files."
acceptFunctiondefault
resizeFunctiondefault

Events

EventArgumentsDescription
dropDragEventThe drop event is fired when an data transfer is dropped on the drop target.
drag-startDragEventThe drag-start event is fired when the user starts dragging an element or text selection.
drag-endDragEventThe drag-end event is fired when a drag operation is being ended (by releasing a mouse button or hitting the escape key).
drag-enterDragEventThe drag-enter event is fired when a dragged element or text selection enters a valid drop target.
drag-overDragEventThe drag-over event is fired when an element or text selection is being dragged over a valid drop target (every few hundred milliseconds).
drag-leaveDragEventThe drag-leave event is fired when a dragged element or text selection leaves a valid drop target.
added-fileVTransmitFileFired on change from the hidden file input after the Native File has been copied to VTransmitFile and added to the component data. (status: 'added')
added-filesVTransmitFile[]Fired on change from the hidden file input after the Native Files have been copied to VTransmitFiles and added to the component data. (status: 'added')
accepted-fileVTransmitFileFired if the user-supplied accept function returns without error. (status: 'added', accepted: true)
rejected-fileVTransmitFileFired if the user-supplied accept function returns an error. Fired AFTER the error event to ensure correct file status. (status: 'error', accepted: false)
accept-completeVTransmitFileFired after the user-supplied accept function has returned regardless of success/failure. Fired after accepted-file & rejected-file. (status: ?, accepted: ?)
removed-fileVTransmitFileFired on the removal of a file.
thumbnailVTransmitFile, Blob\|URLFires on creation of a thumbnail.
errorVTransmitFile, message: String, XmlHttpRequestFired on an ajax upload error. (status: 'error')
error-multipleVTransmitFile[], message: String, XmlHttpRequestFired on an ajax upload error. (status: 'error')
processingVTransmitFileFired after the status is changed to 'uploading', right before the ajax request.
processing-multipleVTransmitFile[]Fired after the status is changed to 'uploading', right before the ajax request.
upload-progressVTransmitFile, progress: Number, bytesSent: NumberFired on progress of the XHR.
total-upload-progressVTransmitFile, totalUploadProgress: NumberFired directly after upload-progress.
sendingVTransmitFile, XmlHttpRequest, FormDataFired right before the XHR is sent.
sending-multipleVTransmitFile[], XmlHttpRequest, FormDataFired right before the XHR is sent.
successVTransmitFile, response: String, ProgressEventFired on load of the XHR.
success-multipleVTransmitFile[], response: String, ProgressEventFired on load of the XHR.
timeoutVTransmitFile, TimeoutEvent, XmlHttpRequestFired on timeout of the XHR.
timeout-multipleVTransmitFile[], TimeoutEvent, XmlHttpRequestFired on timeout of the XHR.
canceledVTransmitFileFired upon cancellation of the XHR. (status: 'canceled')
canceled-multipleVTransmitFile[]Fired upon cancellation of the XHR. (status: 'canceled')
completeVTransmitFileFired upon completion of the XHR. (success or failure)
complete-multipleVTransmitFile[]Fired upon completion of the XHR. (success or failure)
resetn/aFired when all files have been removed.
max-files-exceededVTransmitFileFired if a file is added that exceeds the max files prop.
max-files-reachedVTransmitFile[]Fired when the total accepted files on the instance exceeds the max files prop.
queue-completeVTransmitFileFired once all added files have uploaded and the queue has been flushed.

Slots

Default ($slots.default)

The default slot should contain your markup for getting an upload started. This could be a file uploader button and/or a dropzone.

Files (Scoped, $slots.files)

This slot receives a number of props:

interface FilesSlotProps {
  files: VTransmitFile[];
  acceptedFiles: VTransmitFile[];
  rejectedFiles: VTransmitFile[];
  addedFiles: VTransmitFile[];
  queuedFiles: VTransmitFile[];
  uploadingFiles: VTransmitFile[];
  activeFiles: VTransmitFile[];
  isUploading: Boolean;
}

VTransmitFile

{
  "_nativeFile": {},
  "id": "v-transmit-file-1",
  "accepted": true,
  "lastModified": 1478117443000,
  "lastModifiedDate": "2016-11-02T20:10:43.000Z",
  "name": "cosmo.jpg",
  "processing": true,
  "size": 142776,
  "status": "success",
  "type": "image/jpeg",
  "upload": {
    "bytesSent": 142776,
    "progress": 100,
    "speed": {
      "kbps": 10.06,
      "mbps": 0.01
    },
    "start": 1503273157993,
    "end": 1503273158029,
    "time": 0.036,
    "total": 142776
  },
  "webkitRelativePath": "",
  "width": 700,
  "height": 700,
  "xhr": {},
  "dataUrl":
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAgAElEQVR4XlS9B7RmZ3UluG/="
}

Usage

If you have PHP installed on your machine, you can clone this repo and open up a working test app by running:

npm test

Now navigate to http://localhost:3030/.

<template>
  <main id="root" class="mt-5">
    <div class="container">
      <div class="row">
        <header class="col-12 text-center">
          <h1 class="mb-5"><code>&lt;vue-transmit&gt;</code></h1>
        </header>
        <vue-transmit class="col-12"
                      tag="section"
                      v-bind="options"
                      upload-area-classes="bg-faded"
                      ref="uploader">
          <div class="d-flex align-items-center justify-content-center w-100"
                style="height:50vh; border-radius: 1rem;">
            <button class="btn btn-primary"
                    @click="triggerBrowse">Upload Files</button>
          </div>
          <!-- Scoped slot -->
          <template slot="files" scope="props">
            <div v-for="(file, i) in props.files" :key="file.id" :class="{'mt-5': i === 0}">
              <div class="media">
                <img :src="file.dataUrl" class="img-fluid d-flex mr-3">
                <div class="media-body">
                  <h3>{{ file.name }}</h3>
                  <div class="progress" style="width: 50vw;">
                    <div class="progress-bar bg-success"
                        :style="{width: file.upload.progress + '%'}"></div>
                  </div>
                  <pre>{{ file | json }} </pre>
                </div>
              </div>
            </div>
          </template>
        </vue-transmit>
      </div>
    </div>
  </main>
</template>

<script>
  Vue.use(VueTransmit)
  window.app = new Vue({
    el: '#root',
    data: {
      options: {
        acceptedFileTypes: ['image/*'],
        url: './upload.php',
        clickable: false
      }
    },
    methods: {
      triggerBrowse() {
        this.$refs.uploader.triggerBrowseFiles()
      },
    },
    filters: {
      json(value) {
        return JSON.stringify(value, null, 2)
      }
    }
  })
</script>

Lifecycle

The upload process has many stages, each with different possible outcomes. Here is an overview of the lifecycle of an upload with Vue Transmit:

  • Trigger event
    • input on change: value of input.files is read and passed to vm.addFile
    • target on drop: value of event.dataTransfer["files" || "items"] is read/traversed and passed to vm.addFile
  • Add File
    • instantiate VTransmitFile from native file object (for reactivity & extra info)
    • status added
    • pushed onto vm.files
    • thumbnail is enqueued
  • Accept File
    • check size, type, upload limit
    • invoke accept function for consumer validation
    • accept or reject complete
    • if autoQueue, enqueue file
  • Enqueue file
    • check that file status is added & has been accepted
    • status = queued
    • if autoProcessQueue, invoke processQueue async (like node setImmediate)
  • Process queue
    • check number of uploading files against upload limit
    • invoke processFiles with max amount of queued files options allow
  • Process files
    • do upload
  • Progress updates
  • Complete upload
    • status = success || error
    • process queue to handle buffered files
9.0.0-alpha.12

5 years ago

8.1.4

6 years ago

8.1.3

6 years ago

8.1.2

6 years ago

9.0.0-alpha.11

6 years ago

8.1.1

6 years ago

9.0.0-alpha.10

6 years ago

8.1.0

6 years ago

9.0.0-alpha.9

6 years ago

9.0.0-alpha.8

6 years ago

9.0.0-alpha.7

6 years ago

9.0.0-alpha.6

6 years ago

9.0.0-alpha.5

6 years ago

9.0.0-alpha.4

6 years ago

9.0.0-alpha.3

6 years ago

9.0.0-alpha.2

6 years ago

9.0.0-alpha.1

6 years ago

9.0.0-alpha.0

6 years ago

8.0.0

6 years ago

7.1.7

6 years ago

7.1.6

6 years ago

7.1.5

6 years ago

7.1.4

6 years ago

7.1.3

6 years ago

7.1.2

6 years ago

7.1.1

6 years ago

7.1.0

6 years ago

7.0.6

6 years ago

7.0.5

6 years ago

7.0.4

6 years ago

7.0.3

6 years ago

7.0.2

6 years ago

7.0.1

7 years ago

7.0.0

7 years ago

6.0.8

7 years ago

6.0.7

7 years ago

6.0.6

7 years ago

6.0.5

7 years ago

6.0.4

7 years ago

6.0.3

7 years ago

6.0.2

7 years ago

6.0.1

7 years ago

6.0.0

7 years ago

5.4.0

7 years ago

5.3.2

7 years ago

5.3.1

7 years ago

5.3.0

7 years ago

5.2.0

7 years ago

5.1.5

7 years ago

5.1.4

7 years ago

5.1.3

7 years ago

5.1.2

7 years ago

5.1.1

7 years ago

5.1.0

7 years ago

5.0.1

7 years ago

5.0.0

7 years ago

1.0.12

7 years ago

1.0.11

7 years ago

1.0.10

7 years ago

1.0.9

7 years ago

1.0.8

7 years ago

1.0.7

7 years ago

1.0.5

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago