Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I make sure that the files finished uploading before the form is submitted? #263

Closed
Cohaven opened this issue Mar 13, 2019 · 24 comments

Comments

@Cohaven
Copy link

Cohaven commented Mar 13, 2019

Summary

I'm looking for some sort of validation that would prevent form submission if there's a file still being "processed" by FilePond.

I've looked at the instance options, but haven't found what I'm looking for.

Is there an option or plugin I can use or do I have to write custom code for one of the callbacks/events?

@cs-manughian
Copy link

cs-manughian commented Mar 13, 2019

@Cohaven @pqina I'm implementing the exact same thing! I found this function in the documentation: onprocessfileprogress (https://pqina.nl/filepond/docs/patterns/api/filepond-instance/), which I have been using to disable the submit button if the progress is not 1 (100%):

handleSubmitState(file, progress) {
const isFileUploadPending = progress !== 1;
this.setState({ isSubmitDisabled: isFileUploadPending });
}

However this is only effective for single file uploads. If I have multiple files, the disabled state tends to toggle for each file (i.e. 1 file is complete, so submit button enables, but then the processfileprogress function is triggered again by the next file, thus disabling the submit button again, etc.). If anyone has any advice for how to wait for bulk file progress, that would be greatly appreciated. If you are only allowing for a single file, however, this method works.

@neno91
Copy link

neno91 commented Mar 13, 2019

@Cohaven @pqina I'm implementing the exact same thing! I found this function in the documentation: onprocessfileprogress (https://pqina.nl/filepond/docs/patterns/api/filepond-instance/), which I have been using to disable the submit button if the progress is not 1 (100%), however this is only effective for single file uploads. If I have multiple files, the disabled state tends to toggle for each file (i.e. 1 file is complete, so submit button enables, but then the processfileprogress function is triggered again by the next file, thus disabling the submit button again, etc.). If anyone has any advice for how to wait for bulk file progress, that would be greatly appreciated. If you are only allowing for a single file, however, this method works.

You can avoid the toggeling by checking it like this:
this.pond.getFiles().filter(x=>x.status !== 5).length !== 0

I do this in onprocessfilestart, onprocessfile, onremovefile and onupdatefiles
and save it to a property: isLoading

You might have to add status 2 if you are using initialfiles.

/Neno

@cs-manughian
Copy link

cs-manughian commented Mar 13, 2019

@neno91 Thanks for your reply! That looks like it could work. But this seems like it should be more straightforward, since I'd have to pass my file progress function into four additional function props just to accomplish this task. I'm not currently even using those functions you mentioned. I wonder if there could be a single function called onprocessfilesprogress, which takes in files and progress that behaves exactly like the onprocessfileprogress function, except processing it as a bulk operation. :)

@neno91
Copy link

neno91 commented Mar 13, 2019

@cs-manughian On futher reading i think onprocessfile and onupdatefiles should be enough.

Im currently working on a rather complex implementation myself in react.

I will post back if i find a better way to do it.

@cs-manughian
Copy link

@neno91 Based on the docs, onprocessfile is only for when the upload has completed, but thanks for updating me on your progress!

@rikschennink
Copy link
Collaborator

I agree it would be nice to have a generic state indicator of what is going on inside FilePond, in projects where I use FilePond I currently check if it's busy by doing something similar to @neno91

@Cohaven
Copy link
Author

Cohaven commented Mar 14, 2019

Say I want to add the onprocessfilestart and onupdatefiles callbacks. How would I go about doing that? I'm not seeing callback implementation examples in the docs.

@neno91
Copy link

neno91 commented Mar 14, 2019 via email

@Cohaven
Copy link
Author

Cohaven commented Mar 14, 2019

Just JavaScript.

@rikschennink
Copy link
Collaborator

@Cohaven

const myPond = FilePond.create({
    onprocessfilestart: (file) => {

    },
    onupdatefiles: (files) => {

    }
});

@Cohaven
Copy link
Author

Cohaven commented Mar 14, 2019

The following seems to be working for disabling the submit button while one or more files are being loaded or processed, which is what I was looking for initially.

const inputElement = document.querySelector('input[type="file"]');
const pond = FilePond.create(inputElement, {
    onaddfilestart: (file) => { isLoadingCheck(); },
    onprocessfile: (files) => { isLoadingCheck(); }
});

function isLoadingCheck(){
    var isLoading = pond.getFiles().filter(x=>x.status !== 5).length !== 0;
    if(isLoading) {
        $('#createCaseForm [type="submit"]').attr("disabled", "disabled");
    } else {
        $('#createCaseForm [type="submit"]').removeAttr("disabled");
    }
}

@cs-manughian
Copy link

cs-manughian commented Mar 14, 2019

@Cohaven That works nicely, thank you!! I am using React, so I solved it like this:

<FilePond
    ...
    onaddfilestart={(file) => this.onProcessFiles()}
    onprocessfile={(error, file) => this.onProcessFiles()}>
</FilePond>

Then I bound my onProcessFiles function to my wrapper component and implemented it like so:

onProcessFiles() {
    let { onProcessFiles } = this.props;
    let pondFiles = this.pond.getFiles();
    if (onProcessFiles) onProcessFiles(pondFiles);
}

Then when I used my FilePond wrapper component, I passed in my function implementation:

<FileUploader 
    ....
    onProcessFiles={(pondFiles) => props.onProcessFiles(pondFiles)}  /> 

I would use this as a form field and pass in my function to handle the state of the submit button:

<SomeParentComponentName
    ...
    onProcessFiles={props.handleSubmitState} />

And finally, my button implementation:

  handleSubmitState(pondFiles) {
       const STATUS_COMPLETE = 5;
       const isUploadPending = pondFiles.filter(f => f.status !== STATUS_COMPLETE).length > 0;
       this.setState({ isSubmitDisabled: isUploadPending });
  }

I'd use isSubmitDisabled to set the disabled state of the submit button.

@rikschennink
Copy link
Collaborator

Version 4.3.0 adds onprocessfiles, it's called when all files have been processed.

@rikschennink
Copy link
Collaborator

Version 4.3.1 adds the status property.

Add status property to the FilePond instance, use this property to determine the current FilePond status (EMPTY, IDLE, ERROR, BUSY, or READY).

Will close this issue for now as this should be sufficient to make it easier to control when the user is allowed to submit a parent form.

@vipul1995
Copy link

I'm implementing the exact same thing! I found this function in the documentation: onprocessfileprogress (https://pqina.nl/filepond/docs/patterns/api/filepond-instance/), I have problem when I want to upload multiple files then I am not able to enable or disable submit button as exactly I want.

For example:-
If I have multiple files, the disabled state tends to toggle for each file (i.e. 1 file is complete, so submit button enables, but then the processfileprogress function is triggered again by the next file, thus disabling the submit button again, etc.).

If anyone has any advice for how to wait for bulk file progress, that would be greatly appreciated.

@pqina pqina deleted a comment from ruchi1234 Apr 4, 2019
@GovorukhinAndrey
Copy link

GovorukhinAndrey commented Apr 10, 2019

@rikschennink Hi, how to make onprocessfiles work only for newly uploaded files? Now it does not work if there are already files.

   FilePond.registerPlugin(
      FilePondPluginImageExifOrientation,
      FilePondPluginImagePreview,
      FilePondPluginFileValidateSize,
      FilePondPluginImageCrop,
      FilePondPluginImageResize,
      FilePondPluginFileValidateType
    );

    FilePond.setOptions({
      // allowDrop: false,
      // allowReplace: false,
      status: 4,
      instantUpload: true,
      maxFileSize: '5MB',
      allowImagePreview: true,
      imagePreviewMinHeight: 50,
      imagePreviewMaxHeight: 100,
      imagePreviewMaxFileSize: '5MB',
      imageCropAspectRatio: '1:1',
      // className: 'image-upload',
      server: {
        url: '/images',
        process: {
          url: '/upload',
        },
        revert: '/revert',
        restore: '/restore/',
        load: '/load/',
      },
      files: filepondInitialFiles,
      onremovefile: function(error, file) {
        if (file.serverId) {
          let input = document.createElement('input');
          input.type = 'hidden';
          input.name = 'DeletedFilepondImages';
          input.value = file.serverId;

          uploadForm.appendChild(input);
        }
      },
      onaddfilestart: function(file) {
        console.log(`onaddfilestart`);
        buttonForm.classList.add('filepondUpload');
        buttonForm.setAttribute('disabled', 'true');
      },
      onaddfileprogress(file, progress) {
        console.log(`onaddfileprogress`);
        buttonForm.classList.remove('filepondUpload');
        buttonForm.removeAttribute('disabled');
      },
      onprocessfile: function(file) {
        console.log(`onprocessfile`);
        buttonForm.classList.remove('filepondUpload');
        buttonForm.removeAttribute('disabled');
      },
      onprocessfiles: () => {
        console.log('onprocessfiles');
        buttonForm.classList.remove('filepondUpload');
        buttonForm.removeAttribute('disabled');
      },
    });
    // console.log(fpFiles);
    // get a reference to the input element

    const filepondInput = document.querySelector(
      '#filepondFileUploader input[type="file"]'
    );

    // create a FilePond instance at the input element location
    const filepondObject = FilePond.create(filepondInput, {
      maxFiles: 5,
      allowBrowse: true,
      acceptedFileTypes: ['image/*'],
      files: filepondInitialFiles,
      labelIdle:
        '<div class="image-upload__file-upload-content">Add images</div>',
    });

image
image

@rikschennink
Copy link
Collaborator

You're setting options multiple times files: filepondInitialFiles, in both the setOptions as the creation method. Please create a clean test case.

@GovorukhinAndrey
Copy link

GovorukhinAndrey commented Apr 12, 2019

Updated. The result is the same
`

console.log(filepondInitialFiles);

FilePond.setOptions({
  instantUpload: true,
  allowImagePreview: false,
  server: {
    url: '/images',
    process: {
      url: '/upload',
    },
    revert: '/revert',
    restore: '/restore/',
    load: '/load/',
  },
  onremovefile: function(error, file) {
    if (file.serverId) {
      let input = document.createElement('input');
      input.type = 'hidden';
      input.name = 'DeletedFilepondImages';
      input.value = file.serverId;
      uploadForm.appendChild(input);
    }
  },
  onaddfilestart: function(file) {
    console.log(`onaddfilestart`);
    buttonForm.classList.add('filepondUpload');
    buttonForm.setAttribute('disabled', 'true');
  },
  onaddfileprogress(file, progress) {
    console.log(`onaddfileprogress`);
    buttonForm.classList.remove('filepondUpload');
    buttonForm.removeAttribute('disabled');
  },
});

// get a reference to the input element
const filepondInput = document.querySelector(
  '#filepondFileUploader input[type="file"]'
);

// create a FilePond instance at the input element location
const filepondObject = FilePond.create(filepondInput, {
  maxFiles: 5,
  acceptedFileTypes: ['image/*'],
  labelIdle:
    '<div class="image-upload__file-upload-content">Add images</div>',
  files: filepondInitialFiles,
  onprocessfiles() {
    console.log('onprocessfiles');
    buttonForm.classList.remove('filepondUpload');
    buttonForm.removeAttribute('disabled');
  },
});

`
image
image

@techuila
Copy link

I have the same issue. Is there a solution?

@coreybrett
Copy link

This works for me.

	$('#fform').on('submit',function(e) {
		if (pond.status != 4) {
			return false;
		}
		$(this).find(':input[type=submit]').hide();
		return true;
	});

@interludic
Copy link

Version using jquery

        $('#mapCreateSubmitBtn').on('click',function(e) {
            e.preventDefault();
            
            if ($('.upload-filepond{{$class??''}}').filepond('status') == 4) {
                console.log('submit!');
                $('#mapCreateForm').submit();
            }else{
                const Toast = Swal.mixin({
                    toast: true,
                    position: 'top-end',
                    showConfirmButton: false,
                    timer: 3000,
                })

                Toast.fire({
                icon: 'warning',
                title: 'Upload in progress, please wait before trying again!'
                })

            }
        });

@afsharmn
Copy link

if ( imageFilePond.status === 3 )
{
//uploading...
}

ndeblauw referenced this issue in ndeblauw/blue-admin Apr 14, 2022
* update the edit form

* update the create button

* add functionality to component
@GuiBarradas
Copy link

Updated. The result is the same `

console.log(filepondInitialFiles);

FilePond.setOptions({
  instantUpload: true,
  allowImagePreview: false,
  server: {
    url: '/images',
    process: {
      url: '/upload',
    },
    revert: '/revert',
    restore: '/restore/',
    load: '/load/',
  },
  onremovefile: function(error, file) {
    if (file.serverId) {
      let input = document.createElement('input');
      input.type = 'hidden';
      input.name = 'DeletedFilepondImages';
      input.value = file.serverId;
      uploadForm.appendChild(input);
    }
  },
  onaddfilestart: function(file) {
    console.log(`onaddfilestart`);
    buttonForm.classList.add('filepondUpload');
    buttonForm.setAttribute('disabled', 'true');
  },
  onaddfileprogress(file, progress) {
    console.log(`onaddfileprogress`);
    buttonForm.classList.remove('filepondUpload');
    buttonForm.removeAttribute('disabled');
  },
});

// get a reference to the input element
const filepondInput = document.querySelector(
  '#filepondFileUploader input[type="file"]'
);

// create a FilePond instance at the input element location
const filepondObject = FilePond.create(filepondInput, {
  maxFiles: 5,
  acceptedFileTypes: ['image/*'],
  labelIdle:
    '<div class="image-upload__file-upload-content">Add images</div>',
  files: filepondInitialFiles,
  onprocessfiles() {
    console.log('onprocessfiles');
    buttonForm.classList.remove('filepondUpload');
    buttonForm.removeAttribute('disabled');
  },
});

` image image

did you manage to resolve it? i'm with the same error, i've tried some things but not working at all

@hamzahmd
Copy link

hamzahmd commented Jul 5, 2023

I've just tested the events (@processfiles and @addfilestart) on vue3 and they do the job effectively:

<script setup>
const loadingFiles = ref(false)
</script>

<template>
  <file-pond
  ...
 @processfiles="() => loadingFiles=false"
 @addfilestart="() => loadingFiles=true"
 ...
 />
 </template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests