Closed JoaquimLey closed 6 years ago
Sorry @JoaquimLey I quite new here I i don´t know how to put colors in code. ( I got it 😛)
This is what I have been doing so far and for the time being it is working.
<template>
<div>
<p :class="{'red--text':rule}">{{label}} {{required ? ' *': ''}}</p>
<FilePond
name="file"
ref="input"
:maxFiles="max || 1"
:allowMultiple="allowMultiple"
allowFileTypeValidation="true"
:acceptedFileTypes="type"
:server="{ process, revert, restore, load, fetch }"
:files="files2"
@init="handleFilePondInit"
labelTapToCancel="Toca para cancelar"
labelButtonAbortItemLoad = "Cancelar descarga"
labelButtonRemoveItem = "Borrar archivo"
labelButtonRetryItemLoad="Cargando"
labelButtonRetryItemProcessing ="Reintentar"
labelButtonUndoItemProcessing ="Deshacer"
labelDecimalSeparator =","
labelFileAdded = "Archivo Añadido"
labelFileCountPlural ="Archivos"
labelFileCountSingular ="Archivo"
labelFileLoadError ="Error al subir"
labelFileLoading ="Cargando"
labelFileProcessing ="Subiendo"
labelFileProcessingAborted ="Subida cancelada"
labelFileProcessingComplete ="Subida completa"
labelFileProcessingError ="Error al subir archivo"
labelFileRemoved="Archivo eliminado"
labelFileSizeNotAvailable ="Tamaño no disponible"
labelFileWaitingForSize ="Comprobando tamaño"
labelIdle ="Arrastre un archivo o pulse aqui"
labelTapToRetry="Toca para reintentar"
labelTapToUndo="Toca para deshacer"
labelThousandsSeparator=""
/>
<p v-if="rule" class="caption red--text">Archivo requerido</p>
</div>
</template>
<script>
import FilePond, { registerPlugin } from 'vue-filepond';
// Import FilePond styles
import 'filepond/dist/filepond.min.css';
export default {
name: "file-input",
props: ['label', 'required', 'max', 'type'],
data: function() {
return {
first: true,
files: [], // files uploaded, input
files2: [], // all files
};
},
computed: {
allowMultiple () {
return this.max !== 1
},
rule () {
return this.required && !this.first && this.files.length === 0
}
},
methods: {
process (fieldName, file, metadata, load, error, progress, abort) {
var self = this
try {
progress(true, 0, 1024);
var uploadTask = this.$storage.ref().child('images/' + file.name).put(file, metadata)
uploadTask.on(this.$firebase.storage.TaskEvent.STATE_CHANGED,
function (snapshot) { progress(true, snapshot.bytesTransferred, snapshot.totalBytes)},
function (e) { self.handleError(error, e)},
function () {
load(uploadTask.snapshot.ref.fullPath)
self.files.push(uploadTask.snapshot.ref.fullPath)
}
)
return {
abort: () => {
abort()
uploadTask.cancel();
}
}
} catch (e) {
this.handleError(error, e)
return {
abort: () => { abort() }
}
}
},
revert (uniqueFileId, load, error) {
var self = this
// Create a reference to the file to delete
console.log(uniqueFileId)
var desertRef = this.$storage.ref().child(uniqueFileId);
desertRef.delete().then(function() {
var index = self.files.indexOf(uniqueFileId);
if (index > -1) {
self.files.splice(index, 1);
}
load();
}).catch(function(e) {
this.handleError(error, e)
});
},
load (uniqueFileId, load, error){ error()},
fetch (url, load, error, progress, abort, headers) { error("Solo archivos locales") },
restore (uniqueFileId, load, error, progress, abort, headers) { error() },
handleError (error, e){
switch (e.code) {
case 'storage/canceled':
break;
default: error(e.message)
}
},
handleFilePondInit: function() {
this.$refs.input.getFiles();
}
},
watch:{
files : {
handler: function (val, oldVal) {
if(this.first) this.first = false;
this.$emit('input', val)
},
deep: true
}
},
components: {
FilePond
}
}
</script>
And i call it like this
<file-input
v-else-if="input.type === 'file'"
:label="input.hint"
v-model="input.value"
:rules="rules(input.value, input.rules)"
:required="required(input.rules)"
:max="input.max">
</file-input>
Thanks, @jamesblasco I will look into this later today and get back to it!
Hello @jamesblasco, Thank you so much for giving this awesome example! I copy pasted most of the code and adapted, and it does work 🎉
But now I have a new issue, it only works once 🤔, after the first upload, for some reason when I add more items, nothing happens :(
Have you encountered this issue?
EDIT
@rikschennink maybe you have an idea? 🕺
<template>
<div id="photo-file-upload">
<file-pond
name="filepond"
ref="pond"
label-idle="Click or Drop files here..."
allow-multiple="true"
allow-drop="true"
accepted-file-types="image/jpeg, image/png"
:server="{ process, revert, restore, load, fetch }"
:init="handleFilePondInit"
:warning="handleWarning"
:error="handleError"
:addfile="handleFileAdded"
:processfilestart="handleFileProcessStart"
:processfileprogress="handleFileProcessProgress"
:processfileabort="handleFileProcessAbort"
:processfileundo="handleFileProcessUndo"
:processfile="handleFileProcess"
:onremovefile="handleFileRemoved"/>
</div>
</template>
methods: {
handleFilePondInit() {
console.log("FilePond has initialized");
// this.$refs.pond.getFiles();
},
process(fieldName, file, metadata, load, error, progress, abort) {
console.log("process start");
var self = this;
try {
progress(true, 0, 1);
AlbumsRepository.uploadPhotoToAlbum(
this.albumId,
file,
metadata,
progressCallback => {
progress(true, progressCallback, 1);
console.log("Progress ", progressCallback);
},
status => {
// console.log("Status ", status);
},
url => {
load(url);
console.log("Upload complete at ", url);
},
errorCallback => {
console.log("Upload error ", error);
self.handleError(errorCallback);
}
);
return {
abort: () => {
abort();
// uploadTask.cancel();
}
};
} catch (e) {
this.handleError(error, e);
return {
abort: () => {
abort();
}
};
}
},
load(uniqueFileId, load, error) {
// error();
},
fetch(url, load, error, progress, abort, headers) {
error("Local files only");
},
restore(uniqueFileId, load, error, progress, abort, headers) {
// error();
},
revert(uniqueFileId, load, error) {
// TODO -> AlbumRepository delete photo
load();
},
// func (error[, file, status])
handleWarning(error) {
console.log("Warning file ", file);
},
// func (error[, file, status])
handleError(error, e) {
console.log("Catch error ", e.message);
switch (e.code) {
case "storage/canceled":
break;
default:
error(e.message);
}
},
@JoaquimLey If I understand correctly when adding multiple files, only one of them will upload?
Can't say I spot something odd right away. I assume no errors are thrown?
Is the progressCallback
going from 0 to 1? Or is it a function? That would be weird, but I'm just checking :-)
progress(true, progressCallback, 1);
Yes, let's say I add 5 files at the same time, the five files are uploaded.
But after the user drops one or more files it doesn't do anything else, unless I remove the files from the filepond then it "resumes" upload the other files.
Regarding the progress, I already pass the computed size e.g: progress(true, 0.28, 1)
The progressCallback gets this var
:
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
Maybe I should remove that * 100
🤔 ?
@JoaquimLey I guess that makes it a value from 0
to 100
, not sure if it will fix it but I think the * 100
can be removed.
Hi there @rikschennink, thanks for taking the time
I've removed the * 100
From the DatabaseManager
my progressCallback is called like this:
var progress = (snapshot.bytesTransferred / snapshot.totalBytes);
progressCallback(progress)
And ont he ui component:
process(fieldName, file, metadata, load, error, progress, abort) {
var self = this;
try {
AlbumsRepository.uploadPhotoToAlbum(
this.albumId,
file,
metadata,
progressCallback => {
progress(true, progressCallback, 100);
console.log("Progress ", progressCallback);
},
(...)
}
}
Looking at the UI and the logs, everything seems fine on the progress value side, goes from 0 to 100 value-wise and correctly reflects the %.
But the issue still remains the same, is this something related to the component's :files
? I'm not adding or removing anything related to this :files
, something I noticed @jamesblasco is using 🤔
Here's the whole component:
<template>
<div id="photo-file-upload">
<file-pond
name="filepond"
ref="pond"
label-idle="Click or Drop files here..."
allow-multiple="true"
allow-drop="true"
accepted-file-types="image/jpeg, image/png"
:server="{ process, revert, restore, load, fetch }"
:init="handleFilePondInit"
:warning="handleWarning"
:error="handleError"
:addfile="handleFileAdded"
:processfilestart="handleFileProcessStart"
:processfileprogress="handleFileProcessProgress"
:processfileabort="handleFileProcessAbort"
:processfileundo="handleFileProcessUndo"
:processfile="handleFileProcess"
:onremovefile="handleFileRemoved"/>
</div>
</template>
<script>
// More config for FilePond
// https://pqina.nl/filepond/docs/patterns/plugins/introduction/
// Import Vue FilePond
import vueFilePond from "vue-filepond";
// Import FilePond styles
import "filepond/dist/filepond.min.css";
// Import file type validation plugin
import FilePondPluginFileValidateType from "filepond-plugin-file-validate-type/dist/filepond-plugin-file-validate-type.esm.js";
// Import ImagePreview
import FilePondPluginImagePreview from "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.esm.js";
import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css";
// Create component
const FilePond = vueFilePond(
FilePondPluginFileValidateType
// FilePondPluginImagePreview
);
import AlbumsRepository from "../repositories/AlbumsRepository";
export default {
name: "PhotoFileUpload",
components: {
FilePond
},
props: {
albumId: {
type: String,
required: true
}
},
data() {
return {
files: [],
allFiles: []
};
},
computed: {
currentAlbumId() {
return this.albumId;
}
},
watch: {
},
methods: {
handleFilePondInit() {
console.log("FilePond has initialized");
// this.$refs.pond.getFiles();
},
process(fieldName, file, metadata, load, error, progress, abort) {
console.log("process start");
var self = this;
try {
AlbumsRepository.uploadPhotoToAlbum(
this.albumId,
file,
metadata,
progressCallback => {
progress(true, progressCallback, 100);
console.log("Progress ", progressCallback);
},
status => {
// console.log("Status ", status);
},
url => {
load(url);
console.log("Upload complete at ", url);
},
errorCallback => {
self.handleError(errorCallback);
console.log("Upload error ", errorCallback);
}
);
return {
abort: () => {
abort();
// uploadTask.cancel();
}
};
} catch (e) {
this.handleError(error, e);
console.log("Catched error ", e);
return {
abort: () => {
abort();
}
};
}
},
load(uniqueFileId, load, error) {
// error();
},
fetch(url, load, error, progress, abort, headers) {
error("Local files only");
},
restore(uniqueFileId, load, error, progress, abort, headers) {
// error();
},
revert(uniqueFileId, load, error) {
// TODO -> AlbumRepository delete photo
// load();
},
// all the handleMethods() that only console.log('stuff')
(...)
}
Hi, yes, indeed the same problem happens to me. Unfortunately I can not spend time these next days I'm sorry. As soon as I can, I'll take a look
As I now have the complete code I’ll run some tests on Monday.
On 12 May 2018, 00:10 +0200, jamesblasco notifications@github.com, wrote:
Hi, yes, indeed the same problem happens to me. Unfortunately I can not spend time these next days I'm sorry. As soon as I can, I'll take a look — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
Looking forward to your help, but I would like to thank you both for taking the time and effort to help me out, @jamesblasco @rikschennink 👏🙏.
To clear up, yes there are no errors being thrown, I've deployed the latest code with the logs here:
There is only the ability to upload photos, so "removing" them from the component is just a UI :)
@JoaquimLey @jamesblasco Alright, I know what's happening but I don't know why it's happening.
FilePond will wait with file uploads till there are no more animations running ( this to ensure heavy processing of files, resizing, cropping, does not block animations ). Somehow it thinks that animations are still active and therefore it will not pick-up the newly dropped files. When the finished file is removed it can somehow reach idle state and it starts processing the new files.
Will see if I can reproduce this in the vanilla JS version ( I suspect it's not Vue related ).
@JoaquimLey These event listeners should be prepended with @
or v-on:
instead of :
, I'm not sure if it makes a difference ( it doesn't in my test environment, but the generated HTML looks a bit weird when using :
).
<file-pond
@init="handleFilePondInit"
@warning="handleWarning"
@error="handleError"
@addfile="handleFileAdded"
@processfilestart="handleFileProcessStart"
@processfileprogress="handleFileProcessProgress"
@processfileabort="handleFileProcessAbort"
@processfileundo="handleFileProcessUndo"
@processfile="handleFileProcess"
@removefile="handleFileRemoved"
</file-pond>
@JoaquimLey Can you remove the try-catch so we can see if there's an error being thrown?
@JoaquimLey @jamesblasco Quick update. I've managed to reproduce the problem on my local dev environment. It has to do with the progress
callback.
@JoaquimLey @jamesblasco Turns out something was up with the logic that detected the idle state, working on a fix.
Just published version 1.4.1
of FilePond, should fix the issue.
@rikschennink seriously, I really appreciate the effort you've been putting into maintaining the component.
Once I launch this website you can expect some support from me 100% 👍
Will pull the latest version and check it works, I'm glad that somehow it help catch a bug ;), also good suggestion, should remove that try{}
and force an error to be thrown
No problem @JoaquimLey ! I'm committed to making FilePond an amazingly flexible and robust file upload component, so I'm happy you choose to use it in your project even though it's a relatively young project.
Made it work! Thanks, @rikschennink I'm sure happy with your component, just testing if this will scale since I want so much custom stuff from it.
Now I only have some small issues, like custom error messages showing up etc. but I think we a little bit of digging I can get there :) Thank you once again for your commitement and time! 💪
Fantastic! Glad to hear that @JoaquimLey 🚀
As the original issue has been resolved I'll close it. Do let me know if I can be of further assistance!
Hi i am using vue filepond with laravel. I have one question. How i can show the uploaded images(form the database) in the filepond (Edit Case). Any Help will be appreciated
@amjadkhan896 I'm not sure how this question is related to the original issue.
See this entry in the docs on setting initial files: https://pqina.nl/filepond/docs/patterns/api/filepond-object/#setting-initial-files
Expanding on #14 I would like to know if it is possible to have our own custom methods to handle server callbacks, I'm using Firebase as a DB/Backend and although it is abstracted, I'm using their own implementation, to make it a little more simple to understand, I want to upload a photo to an album, and this is the flow:
Reading the advanced server configuration it looks like this is possible, and this issue on the filepond repo aims to achieve the same result.
But whenever I try to
this.$refs.pond.setOptions({ (...) })
I get an error sayingsetOptions is not a function
.TL;DR:
I would like to know if it is possible to add an example for the
Vue
counterpart of how to setup a custom server configuration, from component init, to assinging custom methods.I also have a WIP app up if you want to test
https://photobook-1337.firebaseapp.com
Login with
Google
orTwitter
-> New album -> Set name -> Create -> Upload photo(s)If you open the console you can see that I'm firing the upload event to the repository when the file is added to the filePond component, but the UI doesn't reflect that :(
My code:
Template
All those methods are only printing to the console so I know what's happening at runtime.
Component init
I've also tried to set the options to this
FilePond
const
but with no luckThe magic
What I would to do:
In a perfect world I can handle all the things I need inside that process method, that has all those nice callbacks.
See also: https://github.com/pqina/filepond/issues/31 Basically the same issue, I just have an abstraction layer on top, I intend to build my own backend after I PoC with Firebase, and sadly the solution wasn't posted 😛
Once again, thanks for the time ! 🎉
Disclaimer: This might be a very stupid issue, but it is the first time I'm doing any dynamic web stuff, so JS, Vue are all new to me.