DropZonejs: Submit form without files - dropzone.js

I've successfully integrated dropzone.js inside an existing form. This form posts the attachments and other inputs like checkboxes, etc.
When I submit the form with attachments, all the inputs post properly. However, I want to make it possible for the user to submit the form without any attachments. Dropzone doesn't allow the form submission unless there is an attachment.
Does anybody know how I can override this default behavior and submit the dropzone.js form without any attachments? Thank you!
$( document ).ready(function () {
Dropzone.options.fileUpload = { // The camelized version of the ID of the form element
// The configuration we've talked about above
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 50,
maxFiles: 50,
addRemoveLinks: true,
clickable: "#clickable",
previewsContainer: ".dropzone-previews",
acceptedFiles: "image/*,application/pdf, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.openxmlformats-officedocument.spreadsheetml.template, application/vnd.openxmlformats-officedocument.presentationml.template, application/vnd.openxmlformats-officedocument.presentationml.slideshow, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.presentationml.slide, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.wordprocessingml.template, application/vnd.ms-excel.addin.macroEnabled.12, application/vnd.ms-excel.sheet.binary.macroEnabled.12,text/rtf,text/plain,audio/*,video/*,.csv,.doc,.xls,.ppt,application/vnd.ms-powerpoint,.pptx",
// The setting up of the dropzone
init: function() {
var myDropzone = this;
// First change the button to actually tell Dropzone to process the queue.
this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
// of the sending event because uploadMultiple is set to true.
this.on("sendingmultiple", function() {
// Gets triggered when the form is actually being sent.
// Hide the success button or the complete form.
});
this.on("successmultiple", function(files, response) {
window.location.replace(response.redirect);
exit();
});
this.on("errormultiple", function(files, response) {
$("#notifications").before('<div class="alert alert-error" id="alert-error"><button type="button" class="close" data-dismiss="alert">×</button><i class="icon-exclamation-sign"></i> There is a problem with the files being uploaded. Please check the form below.</div>');
exit();
});
}
}
});

Use the following:
$('input[type="submit"]').on("click", function (e) {
e.preventDefault();
e.stopPropagation();
var form = $(this).closest('#dropzone-form');
if (form.valid() == true) {
if (myDropzone.getQueuedFiles().length > 0) {
myDropzone.processQueue();
} else {
myDropzone.uploadFiles([]); //send empty
}
}
});
Reference: https://github.com/enyo/dropzone/issues/418

You should check if there are files in the queue. If the queue is empty call directly dropzone.uploadFile(). This method requires you to pass in a file. As stated on [caniuse][1], the File constructor isn't supported on IE/Edge, so just use Blob API, as File API is based on that.
The formData.append() method used in dropzone.uploadFile() requires you to pass an object which implements the Blob interface. That's the reason why you cannot pass in a normal object.
dropzone version 5.2.0 requires the upload.chunked option
if (this.dropzone.getQueuedFiles().length === 0) {
var blob = new Blob();
blob.upload = { 'chunked': this.dropzone.defaultOptions.chunking };
this.dropzone.uploadFile(blob);
} else {
this.dropzone.processQueue();
}

Depending on your situation you could simply submit the form:
if (myDropzone.getQueuedFiles().length > 0) {
myDropzone.processQueue();
} else {
$("#my_form").submit();
}

The first approach is kind of too expensive for me, I would not like to dive into the source code and modify it,
If you happen to be like me , use this.
function submitMyFormWithData(url)
{
formData = new FormData();
//formData.append('nameOfInputField', $('input[name="nameOfInputField"]').val() );
$.ajax({
url: url,
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function(data){
alert(data);
}
});
}
And in your dropzone script
$("#submit").on("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
if (myDropzone.getQueuedFiles().length > 0)
{
myDropzone.processQueue();
} else {
submitMyFormWithData(ajaxURL);
}
});

I tried Matija Grcic's answer and I got the following error:
Uncaught TypeError: Cannot read property 'name' of undefined
And I didn't want to modify the dropzone source code, so I did the following:
if (myDropzone.getQueuedFiles().length > 0) {
myDropzone.processQueue();
} else {
myDropzone.uploadFiles([{name:'nofiles'}]); //send empty
}
Note: I'm passing an object inside the array to the uploadFiles function.
Then I check server-side, if name != 'nofiles' do upload stuff.

Pretty simple, you stop the propagation ONLY if you have files to be submitted via Dropzone:
// First change the button to actually tell Dropzone to process the queue.
this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
// Stop the propagation ONLY if you have files to be submitted via Dropzone
if (myDropzone.getQueuedFiles().length > 0) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
}
});

I have successfully used :
submitButton.addEventListener("click", function () {
if(wrapperThis.files.length){
error = `Please select a file`;
} else {
wrapperThis.processQueue();
}
});

My answer is based on the fact that the other answers don't allow for an Ajax based solution where an actual HTML form isn't actually being used. Additionally you may want the full form contents submitted when sending the Files for upload as well.
As you'll see, my form occurs in a modal outside of any form tag. On completion, the modal is triggered to close.
(FYI getForm returns the form as an object and not directly related to the answer. Also assumes use of jQuery)
init: function() {
var dzClosure = this;
// When saving what are we doing?
$('.saveBtn').off('click').on('click',function(e){
e.preventDefault();
e.stopPropagation();
if (dzClosure.getQueuedFiles().length > 0) {
dzClosure.processQueue();
dzClosure.on('queuecomplete',function(){
$('.modal:visible').modal('hide');
})
} else {
var params = getForm();
$.post(dzClosure.options.url,params,function(){
$('.modal:visible').modal('hide');
})
}
});
dzClosure.on('sending', function (data, xhr, formData) {
var extra = getForm();
for (key in extra){
formData.append(key,extra[key]);
}
});

Related

multiple dropzone causes only first added dropzone to pick up files added to second dropzone

This is how I initiate them:
var myDropzone = new Dropzone("#galleryUploadDropzone", Dropzone.options.myAwesomeDropzone)
var myDropzone = new Dropzone("#galleryUploadDropzone2", Dropzone.options.myAwesomeDropzone2)
Dropzone.options.myAwesomeDropzone and Dropzone.options.myAwesomeDropzone2 are used to initiate them.
Both dropzone initiate correctly with no errors, however when I upload something in the second dropzone upload of it gets displayed in the first dropzone and not the second.
this is how options objects look:
Dropzone.options.myAwesomeDropzone = {
// Dropzone configuration
autoProcessQueue: true,
addRemoveLinks: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 20,
previewsContainer: '#dropzone-previews',
// clickable:'#dropzone-previews',
acceptedFiles: ".jpeg,.jpg,.png,.gif,.bmp",
maxFilesize: 2,
// The setting up of the dropzone
init: function() {
myDropzone = this;
myDropzone.on("addedfile", function(file) {
$( '#uploadMsg' ).hide();
});
myDropzone.on("maxfilesexceeded", function(file) {
$( '#uploadMsg' ).append('<h4>Max amount of files exceeded. Only '+maxFiles+' files can be uploaded at once.</h4>');
});
// First change the button to actually tell Dropzone to process the queue.
$("#sbmtbtn").on('click',function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
// of the sending event because uploadMultiple is set to true.
this.on("sendingmultiple", function() {
// Gets triggered when the form is actually being sent.
// Hide the success button or the complete form.
console.log('sendingmultiple')
});
this.on("successmultiple", function(files, response) {
console.log('successmultiple')
// Gets triggered when the files have successfully been sent.
// Redirect user or notify of success.
setTimeout(removeFiles, 500)
console.log('removeFiles should be called soon')
freshLibraryImages = response.images
});
this.on("errormultiple", function(files, response) {
// alert('error');
// Gets triggered when there was an error sending the files.
// Maybe show form again, and notify user of error
});
}
}
and the second
Dropzone.options.myAwesomeDropzone2 = {
// Dropzone configuration
autoProcessQueue: true,
addRemoveLinks: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 20,
previewsContainer: '#dropzone-previews',
// clickable:'#dropzone-previews',
acceptedFiles: ".jpeg,.jpg,.png,.gif,.bmp",
maxFilesize: 2,
// The setting up of the dropzone
init: function() {
myDropzone2 = this;
myDropzone2.on("addedfile", function(file) {
$( '#uploadMsg' ).hide();
});
myDropzone2.on("maxfilesexceeded", function(file) {
$( '#uploadMsg' ).append('<h4>Max amount of files exceeded. Only '+maxFiles+' files can be uploaded at once.</h4>');
});
// First change the button to actually tell Dropzone to process the queue.
$("#sbmtbtn").on('click',function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
myDropzone2.processQueue();
});
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
// of the sending event because uploadMultiple is set to true.
this.on("sendingmultiple", function() {
// Gets triggered when the form is actually being sent.
// Hide the success button or the complete form.
console.log('sendingmultiple')
});
this.on("successmultiple", function(files, response) {
console.log('successmultiple')
// Gets triggered when the files have successfully been sent.
// Redirect user or notify of success.
setTimeout(removeFiles, 500)
console.log('removeFiles should be called soon')
freshLibraryImages = response.images
});
this.on("errormultiple", function(files, response) {
// alert('error');
// Gets triggered when there was an error sending the files.
// Maybe show form again, and notify user of error
});
}
what am I doing wrong here?
Instantiate the second dropzone to a different variable
var myDropzoneA = new ...
var myDropzoneB = new ...
and refer to them as such

Extjs 4 downloading a file through ajax call

The problem is very simple: i have to download a file when i submit a form, it's an ajax call when the form is submitted which lets me build a file with the data taken from the form, server side, and then send it as a link to an alert. The fact is that my boss want the file to be downloaded directly and not through a link in an alert. So i had to make sure that the file is available server side through tornado(web):
self.set_header('Content-Type', 'application/octet-stream')
self.set_header('Content-Disposition', 'attachment; filename=clients_counter.zip')
with open("static/clients_counter.zip", 'r') as f:
while True:
data = f.read()
if not data:
break
self.write(data)
self.finish()
The server side code seems to work fine, but the client side (extjs4.1) is really a nightmare. This is how my ajax call looks like now, and it doesn't work:
Ext.Ajax.request({
method : "GET",
url : 'http://whatever.com/count?client='+client+'&start='+start+'&end='+end,
timeout : 30000,
success :
function (response) {
//Ext.Msg.alert(response.responseText);
desktop.getWindow('count-win').doClose();
return response;
}//handler,
failure :
function(response) {
alert("Wrong request");
}});
After reading on various sources from Ext JS forum and here in stackoverflow, below is the approach I've chosen (using Ext JS version 4.2.1):
downloadFile: function(config){
config = config || {};
var url = config.url,
method = config.method || 'POST',// Either GET or POST. Default is POST.
params = config.params || {};
// Create form panel. It contains a basic form that we need for the file download.
var form = Ext.create('Ext.form.Panel', {
standardSubmit: true,
url: url,
method: method
});
// Call the submit to begin the file download.
form.submit({
target: '_blank', // Avoids leaving the page.
params: params
});
// Clean-up the form after 100 milliseconds.
// Once the submit is called, the browser does not care anymore with the form object.
Ext.defer(function(){
form.close();
}, 100);
}
I had a similar problem trying to download an Excel File in an Ajax call I solved it this way:
Make a standard sumbit instead of Ajax.
var form = Ext.create('Ext.form.Panel', { // this wolud be your form
standardSubmit: true, // this is the important part
url: '../ObtenerArchivoAdjuntoServlet'
});
form.submit({
params: {
nombreArchivo: nombreArchivo
}
});
After this you would be able return the desired file.
After extracting/reading many posts, I managed to get this simple method to work..
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
standardSubmit: true,
url: 'URL'
}).submit({params: {'PARAM1': param1, 'PARAM2': param2}});
I think you can take a much easier solution. Forget about the ajax, and just get plain old js to open the file for you:
window.open('http://whatever.com/count?client='+client+'&start='+start+'&end='+end)
This will open a new tab and start the download from there.
The following code used to download the file using extjs 5 or 6. Add the following code to method and invoke this for button action. This downloads the file directly insteadof opening in new tab.
use an iframe like this:
/**
* prints the file
*/
printReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
Ext.DomHelper.append(Ext.getBody(), {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: url
});
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
Copied the answer from extjs forum
Option:2
If you want to open the file in new tab
/**
* open file in tab
*/
openReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
var win = window.open('', '_blank');
win.location = url;
win.focus();
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
You cannot use ajax to download file. I've implemented file downloading in extjs which is like ajax. see the blog ajaxlikefiledownload.
FileDownload.downloadFile = function(arguments) {
var url = arguments['url'];
var params = arguments['params'];
var successCallback = arguments['success'];
var failureCallback = arguments['failure'];
var body = Ext.getBody();
var frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenframe-frame',
name:'iframe'
});
var form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: 'POST',
target:'iframe'
});
if (params) {
for (var paramName in params) {
form.createChild({
tag:'input',
cls:'x-hidden',
id:'hiddenform-'+paramName,
type: 'text',
text: params[paramName],
target:'iframe',
value: params[paramName],
name: paramName
});
}
}
form.dom.submit();
FileDownload.isFinished(successCallback,failureCallback);
};
FileDownload.isFinished = function(successCallback,failureCallback) {
//Check if file is started downloading
if (Ext.util.Cookies.get('fileDownload') && Ext.util.Cookies.get('fileDownload')=='true' ) {
//Remove cookie call success callback
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
successCallback();
return;
}
//Check for error / IF any error happens then frame will load with content
try {
if(Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML.length>0){
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
failureCallback();
//Cleanup
Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML = "";
return;
}
}
catch (e) {
console.log(e);
}
console.log('polling..');
// If we are here, it is not loaded. Set things up so we check the status again in 100 milliseconds
window.setTimeout('FileDownload.isFinished('+successCallback+','+failureCallback+')', 100);
};
Usage :
FileDownload.downloadFile({
url : url,
params : params,
success : function(){
//Success call back here
},
failure : function(){
//Failure callbak here
}
});
In the http response you need to add a cookie nammed fileDownload = true
I just had to ad to the success function of the ajax request:
window.open('urltothefile.ext')

Ajax form submit mootools what am I doing wrong

I have following js code:
window.addEvent('domready', function() {
var trigger = $('sendme');
trigger.addEvent( 'click', function(event){
event.preventDefault()
var sendform = new Form.Request($('newform'), {
onSend: function(){
console.log('sending');
},
onComplete: function(){
console.log('sent');
}
});
sendform.send();
});
});
and form with data:
<form action="index.php?option=com_mycomp&layout=edit&id=1" method="post" name="newform" id="newform" class="form-validate">...
the form submits just fine and I can see changes but I get no logs,
thus cant execute actions that I need
form action is not supposed to give me any response back , it is simple post but shouldn't this work? Do I need to send the form to another file that will give me responses like json and submit my form like that ?
what am I doing wrong ?
Any help is appreciated. Thnx!
small update since post ,
I change the form to send data and receive response via json file but still no response messages. everything is being updated so submit works 100%.
right way is new Form.Request($('newform'),console.log(),{
window.addEvent('domready', function() {
var trigger = $('sendme');
trigger.addEvent( 'click', function(event){
event.preventDefault()
var sendform = new Form.Request($('newform'),console.log(), {
onSend: function(){
console.log('sending');
},
onComplete: function(){
console.log('sent');
}
});
sendform.send();
});
});

MVC 3 Client side validation on jQuery dialog

I am showing lots of form using jquery dialog and I wish to add in client side validation on it. I read through some examples, saying that mvc 3 already somehow support jquery client side validation, but I tried by including the necessary script, and my form like this:
#using (Html.BeginForm("CreateFood", "Home", FormMethod.Post, new { id = "formData" }))
{
#Html.ValidationSummary(false, "Please fix these errors.")
When i try to submit my form without fill in the required field, I still dint get any message. Can anyone give me more idea / explanation / examples on this??
Really needs help here... Thanks...
UPDATE (add in the script for my dialog)
$createdialog.dialog("option", "buttons", {
"Cancel": function () {
//alert('Cancel');
$createdialog.dialog('close');
},
"Submit": function () {
var frm = $('#formData');
$.ajax({
url: '/Food/CreateFood',
type: 'POST',
data: frm.serialize(),
success: $createdialog.dialog('close')
});
}
});
Once dropped, open dialog:
// Once drop, open dialog to create food
options.drop = function (event, ui) {
// Get the ContainerImgName which food dropped at
var cimg = $(this).attr('id');
// Pass in ContainerImgName to retrieve respective ContainerID
// Once success, set the container hidden field value in the FoodForm
$.ajax({
url: '/food/getcontainerid',
type: 'GET',
data: { cImg: cimg },
success: function (result) { $('#containerID').val(result); }
});
clear();
$.validator.unobtrusive.parse($createdialog);
$createdialog.dialog('open');
};
I've faced the same problem, solved with:
$(name).dialog({
autoOpen: true,
width: options.witdth,
heigth: options.height,
resizable: true,
draggable: true,
title: options.title,
modal: true,
open: function (event, ui) {
// Enable validation for unobtrusive stuffs
$(this).load(options.url, function () {
var $jQval = $.validator;
$jQval.unobtrusive.parse($(this));
});
}
});
of course you can add the validation on the close event of the dialog, depends on what you're doing, in my case the popup was just for displaying errors so I've performed validation on load of the content. (this pop up is displaying am Action result)
For every dynamically generated form you need to manually run the validator once you inject this content into the DOM as shown in this blog post using the $.validator.unobtrusive.parse function.

jQuery - why ajaxForm bypasses the validation procedure?

I have the following code snippet:
$(document).ready(function () {
// bind 'regFormBody' and provide a simple callback function
$('#regFormBody').ajaxForm(function() {
alert("Thank you for your comment!");
});
// validate the #regFormBody form when it is submitted
$("#regFormBody").validate({
submitHandler: function(form) {
alert('form is submitted');
},
rules: {
...
},
messages: {
...
}
});
}
The problem is that after I add the
// bind 'regFormBody' and provide a simple callback function
$('#regFormBody').ajaxForm(function() {
alert("Thank you for your comment!");
});
The form validation doesn't work at all. I always see the message alert('form is submitted') even without entering any information to form.
May you tell me how to solve this problem?
Thank you
You can expand your options object for .ajaxForm(), like this:
$('#regFormBody').ajaxForm({
beforeSubmit: function() {
return $('#regFormBody').valid();
},
success: function() {
alert('Thanks for your comment!');
}
});
This will kick off validation before submitting, and if it's not .valid() it'll stop the submit from happening like you want.

Resources