Last active
May 1, 2019 16:12
-
-
Save cseelus/63baa4f46f6f0ae0c4630a3987022f97 to your computer and use it in GitHub Desktop.
Uploading files automatically with ActiveStorage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DirectUpload } from 'activestorage' | |
// See DirectUploadController from Rails Active Storage source | |
export class CustomUploader { | |
constructor(input, file) { | |
this.input = input | |
this.file = file | |
this.directUpload = new DirectUpload(this.file, this.url, this) | |
this.dispatch("initialize") | |
} | |
start() { | |
const hiddenInput = document.createElement("input") | |
hiddenInput.type = "hidden" | |
hiddenInput.name = this.input.name | |
hiddenInput.classList.add('cache') | |
this.input.insertAdjacentElement("beforebegin", hiddenInput) | |
this.dispatch("start") | |
this.directUpload.create((error, attributes) => { | |
if (error) { | |
hiddenInput.parentNode.removeChild(hiddenInput) | |
this.dispatchError(error) | |
} else { | |
hiddenInput.value = attributes.signed_id | |
} | |
this.dispatch("end") | |
// callback(error) | |
}) | |
} | |
uploadRequestDidProgress(event) { | |
const progress = event.loaded / event.total * 100 | |
if (progress) { | |
this.dispatch("progress", { progress }) | |
} | |
} | |
get url() { | |
return this.input.getAttribute("data-direct-upload-url") | |
} | |
dispatch(name, detail = {}) { | |
detail.file = this.file | |
detail.id = this.directUpload.id | |
return dispatchEvent(this.input, `direct-upload:${name}`, { detail }) | |
} | |
dispatchError(error) { | |
const event = this.dispatch("error", { error }) | |
if (!event.defaultPrevented) { | |
alert(error) | |
} | |
} | |
directUploadWillStoreFileWithXHR(xhr) { | |
this.dispatch("before-storage-request", { xhr }) | |
xhr.upload.addEventListener("progress", event => this.uploadRequestDidProgress(event)) | |
} | |
} | |
function dispatchEvent(element, type, eventInit = {}) { | |
const { disabled } = element | |
const { bubbles, cancelable, detail } = eventInit | |
const event = document.createEvent("Event") | |
event.initEvent(type, bubbles || true, cancelable || true) | |
event.detail = detail || {} | |
try { | |
element.disabled = false | |
element.dispatchEvent(event) | |
} finally { | |
element.disabled = disabled | |
} | |
return event | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { CustomUploader } from 'custom_uploader' | |
// Handle change, e.g. User attaches a file | |
const inputs = Array.from(document.querySelectorAll('.custom-file-input')) | |
inputs.forEach(input => { | |
input.addEventListener('change', event => { | |
Array.from(input.files).forEach( file => { | |
const uploader = new CustomUploader(input, file) | |
uploader.start(file) | |
}) | |
// clear the selected files from the input | |
input.value = null | |
}) | |
}) | |
addEventListener('direct-upload:initialize', event => { | |
// … see https://guides.rubyonrails.org/active_storage_overview.html#example how to use the callbacks for displaying progress | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment