Reset Dropzone inside a Modal box - ajax

I have a form inside a modal box of a bootstrap theme. The form contains few input fields and a Dropzone field, all of which sends the data across to the server through ajax. After filling the form, I, obviously need to reset the form for next set of inputs. I have managed to successfully reset the form fields, EXCEPT the Dropzone image.
So now when I click submit, after filling the form, the data is entered. On clicking the button to open the modal again to add a new set, the previous image is still shown there. I need that also to be gone.
I kept searching for a solution on S.O and many other places. I couldn't get a solution. Any guidance is appreciated.
HTML:
<form enctype="multipart/form-data" id="addProductImageForm" class="dropzone dz-clickable" action="#">
<div class="dz-default dz-message" ><span>Click here to upload Product Image</span></div>
</form>
JS:
Dropzone.options.addProductImageForm = {
paramName: "productImage",
maxFilesize: 2,
maxFiles: 1,
uploadMultiple: false,
acceptedFiles: "image/*",
dictDefaultMessage: "Click to Upload",
addRemoveLinks: true,
accept: function(file, done) {
if (file.name == "bg.png") {
done("Naha, you don't.");
}
else {
done();
}
},
success: function(d, response, test) {
var value = response.replace("int(0)", "");
var value2 = value.replace(/(\r\n|\n|\r)/gm, "");
$('#product_imageName').val(value2);
},
init: function() {
this.on("maxfilesexceeded", function(file) {
alert("No more files please!");
});
}
};
$("#addProductImageForm").dropzone({url: "/path/to/upload_product_image.php"});
.
.
.
.
var formData = {
(input values here)
};
$.ajax({
type: 'POST',
url: 'path/to/projectsAction.php',
data: formData,
encode: true
})
.done(function(data) {
var value3 = data.replace(/(\r\n|\n|\r)/gm, "");
$('#project_productId').append('<option value="' + value3 + '" selected="selected">' + formData.product_name + '</option>');
$("#addProductForm").find("input[type=text], textarea, select").val("");
$("#addProductImageForm").html("");// THIS IS THE LINE THAT REMOVES THE THUMBNAIL. (From the answer given by xrcwrn)
$('.close').click();
});
event.preventDefault();

If you are using dropzone like
<form action="/file-upload"
class="dropzone"
id="my-awesome-dropzone"></form>
after posting your data reset your dropzone container like
$("#my-awesome-dropzone").html("");

Related

Form-data only append last multiple selection

This may be duplicate but I can't solve it.
I can send multiple images by JQuery/Ajax to my server (Asp.Net Core) and save them successfully. But the problem is when I want to add the second batch files, the first batch will not append to form data. I add images with a button and not by input type="file" field.
HTML:
<form asp-area="User" asp-controller="Item" asp-action="Create" id="createForm" method="post" enctype="multipart/form-data" >
<input asp-for="ImageUrl" id="myInput" type="file" name="inputFile[]" accept="image/*" multiple style="display:none" />
<button id="myButton" type="button">+ Add Files</button>
JS:
$(document).ready(function () {
var inputFile = $('#myInput');
$('#myButton').click(function () {
$('#myInput').click();
});
var files = [];
$('#myInput').change(function () {
var newFiles = [];
for (var index = 0; index < inputFile[0].files.length; index++)
{
let file = inputFile[0].files[index];
files.push(file);
}
});
});
$("#createForm").submit(function (e) {
e.preventDefault();
var formData = new FormData(document.getElementById('createForm'));
//var formData = new FormData(this);
files.forEach(file => {
formData.append('file[]', file);
});
for (var pair of formData.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
$.ajax({
type: "POST",
cache: false,
processData: false,
contentType: false,
url: $("#createForm").attr('action'),
enctype: 'multipart/form-data',
data: new FormData(this),
});
});
});
Suppose I choose pictures 1,2,3 and submit my form and all 3 pictures save to server side successfully. Now let's try a new record: I add pictures 1,2,3, after that I choose pictures 4,5,6 so I expect to 6 images to be appended to form data. But only the last selection 4,5,6 are saved to server !
This is my console report in below.As you can see I have input-File[]=3 !! Something like I have no jquery and no ajax and just using pure HTML/Input Multiple file and I can upload only my last selections !!
But when I refresh my page and choose just 1,2,3 images (one selection only), I have input-File[]=3 and file[], [object File]=3 and every thing is good.
I tried data: new FormData() and data: formData and many other options on data parameter but no one could solve my problem :(
Update : ******************************:
Case 1:
var formData = new FormData(document.getElementById('createForm'));
. . .
data: formData,
Results: No image save in server and ImageUrl is null in database.
Case 2:
var formData = new FormData()
. . .
data: formData,
Results in error in console : XML Parsing Error: no root element found
Case 3:
var formData = new FormData(this)
. . .
data: formData,
Results : suppose I select images 1,2,3 at first and then select images 4,5,6. I have images 1,2,3,4,5,6 saved on server and 4,5,6 save twice !! I'm getting near but still can't manage it.
.
I think there might be an error in the way that you copied your code. There is an extra }); after $('#myInput').change(function () { ... });
I'm assuming that is not part of the issue and was just a mistake in pasting it over.
The issue I think is that you were trying to send the files over separately from the inputFiles. Updating the for loop in the submit event handler should give you what you are wanting.
$("#createForm").submit(function (e) {
e.preventDefault();
var formData = new FormData();
files.forEach((file) => {
formData.append('inputFile[]', file);
});
for (var pair of formData.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
$.ajax({
type: "POST",
cache: false,
processData: false,
contentType: false,
url: $("#createForm").attr('action'),
enctype: 'multipart/form-data',
data: formData,
});
});

Ajax submit an image with form - pass the FormData - trigger submit

I simply want to use ajax to submit a form with an image from a phone.
If I use the below code as a simple function - the form data is not passed.
If I use the code as is - it works but the user has to click the submit button.
How do I either pass the FormData properly to a simple $.ajax({}); submit?
OR
How do I trigger the code below when a picture is taken or selected?
I have this - it works fine when user clicks submit:
// how do I trigger this when image file is selected?
$("#Upload_Form").submit(function(e){
e.preventDefault();
// OR - how do I get FormData with image without using: '$("#Upload_Form").submit(function(e)'
var formData = new FormData(this);
$.ajax({
// POST details are here etc.
});
});
Bind the change event for the file input like below and then trigger the submit event of the form or make an ajax call right away with the FormData see below demo.
If you want to know how to submit image using FormData and ajax see this answer
$("#my-form").on('submit', function(e) {
e.preventDefault();
// OR - how do I get FormData with image without using: '$("#Upload_Form").submit(function(e)'
var formData = new FormData(this);
console.log("sending Ajax call now");
$.ajax({
// POST details are here etc.
});
});
$("#my-file").on('change', function() {
//you can either trigger the form submit here
var form = $("#my-form");
$("#my-form").submit();
//OR
//use this to send the ajax call to upload the image
// var form=$("#my-form")[0];
// var formData = new FormData(form);
// $.ajax({
// type: "POST",
// url: 'your/url',
// data: formData,
// processData: false,
// contentType: false,
// success: function (data) {
// console.log("SUCCESS : ", data);
// },
// error: function (e) {
// console.log("ERROR : ", e);
// }
// });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="my-form" enctype="multipart/form-data">
<input type="file" name="my-file" id="my-file" />
<input type="submit" name="submit" value="submit" />
</form>
Update
Note: if you want to use an ajax call to send the formData you need to set the processData and contentType to false. contentType: false only available from jQuery 1.6 onwards.

How to change url dropzone? URL dynamically with ajax success

I read this: https://github.com/enyo/dropzone/wiki/Set-URL-dynamically but i dont got success... :(
I have 1 form...
And i send the inputs with ajax.
The ajax returns the new id of user. in this moment i want to change de url dropzone for to set path to id of the new user.
$.ajax({
type: "POST",
url: "class/inserir.php?funcao=teste",
data: formdata,
dataType: "json",
success: function(json){
if(json.sucesso=="sim"){
alert("Wait! Sending Pictures.");
this.options.url = "class/upload_img.php?"+json.id;
myDropzone.processQueue();
}else{
location.href="home.php?ir=cad_animal&cad=nao&erro="+json.erro;
}
}
});
var myDropzone = new Dropzone("#imagens", {
url: "class/upload_imgteste.php",
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 1, // MB
addRemoveLinks : true,
dictResponseError: "Não foi possível enviar o arquivo!",
autoProcessQueue: false,
thumbnailWidth: 138,
thumbnailHeight: 120,
});
sorry for my bad english!
Thanks for all.
You may add a function on dropzone's "processing" event listener.
Dropzone.options.myDropzone = {
init: function() {
this.on("processing", function(file) {
this.options.url = "/some-other-url";
});
}
};
Here is the link where I got the code and it works for me: https://github.com/enyo/dropzone/wiki/Set-URL-dynamically
change this
this.options.url = "class/upload_img.php?"+json.id;
to this
myDropzone.options.url = "class/upload_img.php?"+json.id;
Does that work?
New answer for an old question only because I found this answer and the link to the dropzone wiki and didn't like it. Modifying the options of the plugin multiple times like that seems very wrong.
When dropzone uses some options it runs it through a resolveOption function passing in a files array. In the current branch you can define a function for the options: method, url and timeout.
Here's a complete working example including delaying for the ajax:
Dropzone.autoDiscover = false;
const doStuffAsync = (file, done) => {
fetch('https://httpbin.org/get').then((response) => {
file.dynamicUploadUrl = `https://This-URL-will-be-different-for-every-file${Math.random()}`
done();//call the dropzone done
})
}
const getMeSomeUrl = (files) => {
return `${files[0].dynamicUploadUrl}?sugar&spice`;
}
let myDropzone = new Dropzone("#my-awesome-dropzone", {
method: "put",
accept: doStuffAsync,
url: getMeSomeUrl
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.4.0/min/dropzone.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.4.0/min/dropzone.min.css">
<form action="/file-upload" class="dropzone" id="my-awesome-dropzone">
</form>
If you need to change the URL dropzone posts to dynamically for each file, you can use the processingfile event and change the options.url.
<form id="my-dropzone" action="/some-url" class="dropzone"></form>
<script>
Dropzone.options.myDropzone = {
init: function() {
this.on("processing", function(file) {
this.options.url = "/some-other-url";
});
}
};
</script>
Another way that worked for me (accept event callback):
$('div#dropzone').dropzone({
options...,
accept: function (file, done) {
this.options.url = 'the url you want';
}
});
BlueWater86's answer didn't work for me. But I agree that changing myDropzone.options.url each time is bad practice, and it actually doesn't work if you are dragging a lot of files into the uploader at the same time.
I wrote the following code and it works well for uploading one file at time and for many at a time. I'm using Backblaze B2 but it should also work for S3.
myDropzone.on('addedfile', function(file) {
options = {
filename: file.name,
type: file.type,
_: Date.now()
};
// Make the request for the presigned Backblaze B2 information, then attach it
$.ajax({
url: '/presign_b2',
data: options,
type: 'GET',
success: function(response){
file.dynamicUrl = response['url'];
myDropzone.enqueueFile(file);
}
});
});
myDropzone.on('sending', function(file, xhr) {
xhr.open("PUT", file.dynamicUrl); // update the URL of the request here
var _send = xhr.send;
xhr.send = function() {
_send.call(xhr, file);
}
});

Ajax loaded content div class is not applied

I have a page that has a few divs connected in a flowchart via JS-Graph.It. When you click one of the divs, I want it to 1) generate text in a special div 2) generate a popup via click functions attached to the two classes "block" and "channel" in each div. This works when the page is static.
When I add ajax so on click of a button and add more divs, only one of the two classes appears in the HTML source. "Channel" is no longer visible and the function to generate a pop-up on click of a channel class div does not work anymore...
AJAX call:
$("#trace").bind('click', $.proxy(function(event) {
var button2 = $('#combo').val();
if(button2 == 'default') {
var trans = 'Default View';
}
if(button2 == 'abc') {
var trans = 'abc';
}
$.ajax({ // ajax call starts
url: 'serverside.php', // JQuery loads serverside.php
data: 'button2=' + $('#combo').val(), // Send value of the clicked button
dataType: 'json', // Choosing a JSON datatype
success: function(data) // Variable data constains the data we get from serverside
{
JSGraphIt.delCanvas('mainCanvas');
$('.test').html('<h1>' + trans + '</h1>'); // Clear #content div
$('#mainCanvas').html(''); // Clear #content div
$('#mainCanvas').append(data);
JSGraphIt.initPageObjects();
}
});
return false; // keeps the page from not refreshing
}, this));
DIV class: (works in index.php but not transactions.php)
// Boxes
while($row = sqlsrv_fetch_array($result))
{
echo '<div id="'.$row['id'].'_block" class="block channel" style="background:';
Functions:
$(document).on('click', '.block', $.proxy(function(event) {
var input = $(event.target).attr('id');
var lines = input.split('_');
var button = lines[0];
$.ajax({
url: 'srv.php',
data: 'button=' + button,
dataType: 'json',
success: function(data)
{
$('#content').html('');
$('#content').append(data);
}
});
return false;
}, this)); // End Application Details
$(".channel").click(function () {
alert('channel');
});
Something about registering with pages, I'm not sure exactly how it works. The fix should be to change your channel click function to be the same as your first and use the .on('click') option.
found some related reading material. https://learn.jquery.com/events/event-delegation/

DropZonejs: Submit form without files

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]);
}
});

Resources