Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Active Storage Upload - Vue example

  • progress not working yet,
  • yarn add activestorage

USAGE

  active-storage-upload
    = f.file_field :attachments, multiple: true, direct_upload: true
    - f.object.attachments.each do |att|
      .list-group-item
        = att.filename
<template lang='pug'>
div.drop-zone(:class='{dragging: isDragging }'
@dragover.prevent='dragover'
@dragenter.prevent='dragover'
@drop.prevent.stop='onDrop'
@dragleave.prevent='dragleave')
div(:class='{ hidden: uploadInProgress }')
slot(ref='slot')
.list-group
.list-group-item(v-for='file in finished')
input(:name='input.name' type='hidden' :value='file.blob.signed_id')
|{{file.blob.filename}}
.list-group-item(v-for='file in uploads')
i Upload: {{file.file.filename }}
</template>
<script>
/* eslint-disable no-restricted-globals */
/* eslint-disable prefer-destructuring */
import { DirectUpload } from 'activestorage'
export default {
data() {
return {
isDragging: false,
finished: [],
uploads: [],
}
},
beforeDestroy() {
removeEventListener("direct-upload:progress", this.onProgress.bind(this))
},
mounted() {
addEventListener("direct-upload:progress", this.onProgress.bind(this))
this.input.addEventListener('change', (_event) => {
Array.from(this.input.files).forEach(file => this.upload(file))
this.input.value = null
})
},
methods: {
dragover() {
this.isDragging = true
},
dragleave() {
this.isDragging = false
},
onDrop(event) {
this.dragleave();
const files = event.dataTransfer.files;
Array.from(files).forEach(file => this.upload(file))
},
onProgress(event) {
console.log('progress', event)
},
upload(file) {
if (!this.uploadInProgress) {
addEventListener("direct-upload:progress", this.onProgress.bind(this))
}
const upload = new DirectUpload(file, this.uploadUrl)
this.uploads.push({ file, upload })
upload.create((error, blob) => {
if (error) {
// TODO
} else {
this.uploads = this.uploads.filter(payload => payload.file.filename !== file.filename)
this.finished.push({ file, blob })
if (this.uploads.length === 0) {
removeEventListener("direct-upload:progress", this.onProgress.bind(this))
}
}
})
},
},
computed: {
uploadInProgress() { return this.uploads.length > 0 },
uploadUrl() { return this.input.dataset.directUploadUrl },
input() {
return this.$el.querySelector('input[type=file]');
}
}
}
</script>
<style lang='scss'>
.drop-zone {
border: 3px solid transparent;
margin: -3px;
}
.drop-zone.dragging {
border: 3px dashed #444;
position: relative;
}
.drop-zone.dragging:before {
content: "Drop the file here to upload";
display: block;
position: absolute;
top: 0;
right: 5px;
font-style: italic;
color: #555;
}
input[type=file][data-direct-upload-url][disabled] {
display: none;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.