I have a mvc form with multiple fields that are calling custom edit views.
I need to implement dropzone instead of the standard file import control.
I cant figure out how to get the file names and pass them together with the dropzone. I am searching the internet for 2 days and no results.
The form looks like this:
#using (Html.BeginForm("contr", "action", new { themeid = ViewBag.ThemeId, #class = "dropzone"}, FormMethod.Post, new { #enctype = "multipart/form-data" }))
At the end I have an Edit view that contains the dropzone div:
<div id="fileInput" class="dropzone">
<div class="fallback">
<input name="files" type="file" multiple />
</div>
</div>
Function for the dropzone:
function initDropzone() {
new Dropzone('#fileInput', {
url: '#',
autoProcessQueue: false,
uploadMultiple: true,
addRemoveLinks: true,
autoDiscover: false,
parallelUploads: 100,
dictDefaultMessage: "Click or drop files to upload",
init: function () {
var myDropzone = this;
$('#submit-all').click(function (e) {
$(".dz-progress").show();
myDropzone.processQueue();
});
myDropzone.on('success', function () {
myDropzone.removeAllFiles();
//$('#name').val('');
});
myDropzone.on("sending", function (file, xhr, formData) {
formData.append("file", file); // Append all the additional input data of your form here!
});
myDropzone.on("addedfile", function (event) {
$(".dz-progress").hide();
});
}
});
As most examples suggest I call processQueue when submit is clicked, but the problem is that the controller action is called twice, once with the files but without the other models, and the next time with the models but without the files.
I can't use stopPropagation on submit because I call different views based on the logic in the action method.
The basic question is how I can take the files from dropzone and append them to form data.
Hidden fields does not work, I don't know why.
Any help would be appreciated.
Related
Uppy is used for uploading files by drag & drop interface.
I want to pass a value input given by user from html interface
but the javascript is already processed before the user gives his input.
if i use .onchange() with the userinput then it does not destroy/clear the previously created file drop area but creates too many new file drop areas inside #drag-drop-area
<input id="userinput" value="Car">
<div id="#drag-drop-area"></div>
var userinput = document.getElementById("userinput").value
var URL = 'example.com/post-submit/?category='+userinput;
var uppy = Uppy.Core()
.use(Uppy.Dashboard, {
inline: true,
target: '#drag-drop-area',
inputName: 'imageFile[]',
height:"250px",
width:"100%"
})
.use(Uppy.XHRUpload, {endpoint: URL", headers: {
'X-CSRF-Token': " {{csrf_token()}} "}
})
uppy.on('complete', (result) => {
console.log('Upload complete! ', result.successful)
})
I am using the same dropzone form to upload different documents. After upload I need to open a modal for each one document to give the possibility to modify, so i show document uploaded inside the dropzone when i open the modal with this code
$("#mydropzone").dropzone({
acceptedFiles: ".pdf,.tiff,.png,.jpeg,.jpg,.bmp",
dictDefaultMessage: "Drop files or click here to upload a new DICOM series ...",
uploadMultiple: true,
parallelUploads: 10,
paramName: "file",
autoProcessQueue: false,
clickable:'#dropzoneModal',
previewTemplate: document.querySelector('#preview_template').innerHTML,
init : function() {
modalDropzone = this;
fatturaId = thisId-1;
for(var i=0;i<dropzones[fatturaId].files.length;i++){
var mockFile = {
name: dropzones[fatturaId].files[i].name,
size: dropzones[fatturaId].files[i].size,
status: Dropzone.ADDED,
accepted: true
};
modalDropzone.emit("addedfile", mockFile);
modalDropzone.files.push(mockFile);
modalDropzone.createThumbnailFromUrl(mockFile, opts.imageURL, function() {
modalDropzone.emit("complete", mockFile);
})
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The documents uploaded are saved in dropzones[fatturaId].files, that why i iterate it
The first time the file shows correctly when i open the edit modal, while the second time the dropzone shows empty without any document in it, showing an error in console:
Uncaught Error: Dropzone already attached.
I'm trying to implement the dropzone.js to my existing form, which has a lot of input fields, select options, etc. I tried to follow this answer: https://stackoverflow.com/a/35275260/13695248 but all I earned is if I press the send button, literally nothing happens. No error or anything, it just doesn't do anything. I've got a lot of help from #Swati so I have some extra functions in the dropzone options, but I don't think it causes the problem.
This is how the html looks like:
<form action="upload.php" method="post" enctype='multipart/form-data' id="add">
<div class="dropzone" id="uploader"></div>
<input type="text" id="mainimage" name="mainimage">
<!-- lot of input fields here -->
<input type="submit" class="btn btn-primary btn-xl" id="sendButton" name="upload" value="Send" />
</form>
and the JS part:
Dropzone.options.uploader = {
url: 'upload.php',
autoProcessQueue: false,
uploadMultiple: true,
paramName: "images", // The name that will be used to transfer the file
maxFilesize: 2, // MB
maxFiles: 5,
addRemoveLinks: true,
acceptedFiles: 'image/*',
accept: function(file) {
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onloadend = function() {
$('<a>', {
class: 'primary',
text: "Legyen ez a fő kép",
href: "#"
}).appendTo(file.previewElement)
//file.previewElement.append($textContainer)
console.log(file.previewElement)
file.previewElement.classList.add("dz-success");
if (($(".dz-success.dz-complete").length > 0) && ($(".main").length == 0)) {
$(".dz-success.dz-complete:first .primary").text("Fő kép")
//add class to first one
$(".dz-success.dz-complete:first").addClass("main")
$("#mainimage").val($(".dz-success.dz-complete:first").find(".dz-filename span").text()) //add default name to imgs input
}
}
file.previewElement.classList.add("dz-complete");
},
"error": function(file, message, xhr) {
if (xhr == null) this.removeFile(file);
alert(message);
},
removedfile: function(file) {
var is_there = file.previewElement.classList.contains("main");
console.log(is_there)
file.previewElement.remove();
if (is_there && $(".dz-success.dz-complete").length > 0) {
$(".dz-success.dz-complete .primary").text("Legyen ez a fő kép")
$(".dz-success.dz-complete:first .primary").text("Fő kép")
$(".dz-success.dz-complete:first").addClass("main")
$("#mainimage").val($(".dz-success.dz-complete:first").find(".dz-filename span").text()) //add default name to imgs input
}
if ($(".dz-success.dz-complete").length == 0) {
$("#mainimage").val("")
}
},
init: function() {
dzClosure = this; // Makes sure that 'this' is understood inside the functions below.
// for Dropzone to process the queue (instead of default form behavior):
document.getElementById("sendButton").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
dzClosure.processQueue();
});
//send all the form data along with the files:
this.on("sendingmultiple", function(data, xhr, formData) {
$(":input[name]", $("form")).each(function() {
formData.append(this.name, $(':input[name=' + this.name + ']', $("form")).val());
});
});
},
dictDefaultMessage: 'Kérjük húzza ide a képeket vagy kattintson a tallózáshoz!',
dictFallbackMessage: 'Böngészője nem támogatja a kép előnézetet!',
dictFallbackText: 'Kérjük használja a tallózást a képek kiválasztásához!',
dictFileTooBig: 'A fájl mérete túl nagy. ({{filesize}}MiB). Maximum {{maxFilesize}}MiB lehet!',
dictInvalidFileType: 'A kiválasztott fájl kiterjesztése nem megfelelő!',
dictResponseError: 'A szerver {{statusCode}} kóddal válaszolt. Kérjük próbálja meg később!',
dictCancelUpload: 'Feltöltés visszavonása',
dictUploadCanceled: 'feltöltés visszavonva!',
dictCancelUploadConfirmation: 'Biztosan visszavonja a feltöltést?',
dictRemoveFile: 'Kép törlése',
dictMaxFilesExceeded: 'Elérte a maximálisan feltölthető képek számát!'
};
$(document).on("click", ".primary", function() {
$(".dz-success.dz-complete.main .primary").text("Legyen ez a fő kép")
$(this).text("Fő kép")
$(".dz-success.dz-complete").removeClass("main")
$(this).closest(".dz-success.dz-complete").addClass("main")
$("#mainimage").val($(this).closest(".dz-success.dz-complete").find(".dz-filename span").text())
})
I think this init function ruins it, because if I delete it, the button works fine but the data doesn't go to the database
init: function() {
dzClosure = this; // Makes sure that 'this' is understood inside the functions below.
// for Dropzone to process the queue (instead of default form behavior):
document.getElementById("sendButton").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
dzClosure.processQueue();
});
//send all the form data along with the files:
this.on("sendingmultiple", function(data, xhr, formData) {
$(":input[name]", $("form")).each(function() {
formData.append(this.name, $(':input[name=' + this.name + ']', $("form")).val());
});
});
}
I had to add 'done' to the accept function:
accept: function(file, done) {
.
.
done();
}
I am confuse i dont know how to access parent div. Let me summarize it!
Actually i have multiple dropzone which i initialize using class '.abc'
above each dropzone there is input where i put image name for uploading. here is my code
$('.kt_dropzone_1').dropzone({
url: base_url + 'product/uploadPic', // Set the url for your upload script location
paramName: "file", // The name that will be used to transfer the
maxFiles: 1,
maxFilesize: 5, // MB
addRemoveLinks: true,
accept: function (file, done) {
done();
},
success: function (file, response) {
alert($(this).attr('data-abc')); // undefined
alert($(this).parent().parent.html()); // undefined
},
});
here is html this is in looop so consider it multiple
<input type="hidden" class="img-upload" name="old" value=""/>
<div class="col-md-12 pull-left">
<div class="dropzone dropzone-default kt_dropzone_1">
<div class="dropzone-msg dz-message needsclick">
<h3 class="dropzone-msg-title">Drop files here or click to upload.</h3>
<span class="dropzone-msg-desc">This is just a demo
dropzone. Selected files are <strong>not</strong>
actually uploaded.</span>
</div>
</div>
</div>
i try use custom attribute to pass input id dynamic still not work
i dont know how to get current div object to access parent html or input or div
I could suggest you small changes for this. Move input type hidden inside of
and just above the dropzone div.
Now to refer the correct dropzone please give a try to following updated code.
$('.kt_dropzone_1').dropzone({
var this_dropzone = $(this);
url: base_url + 'product/uploadPic', // Set the url for your upload script location
paramName: "file", // The name that will be used to transfer the
maxFiles: 1,
maxFilesize: 5, // MB
addRemoveLinks: true,
accept: function (file, done) {
done();
},
success: function (file, response) {
this_dropzone.closest("div").find(".img-upload").attr('data-abe', 'value to be set');
this_dropzone.closest("div").find(".img-upload").val('you can set anyvalue here');
},
});
This should work as you want!
My model looks like:
class Store
{
...
virtual ICollection<StoreItem> items;
...
}
The View for the Store Shows Store properties and a table with items and StoreItem properties.
I want that when an Item is clicked, and a jQuery UI dialog is displayed to edit the Item model. For this, I created Views actions for StoreItem, and embedded a partial frame in the Dialog.
Something like:
<div id="modaldlg" title="Edit item?">
#using (Ajax.BeginForm(
new AjaxOptions
{
HttpMethod = "get",
InsertionMode = InsertionMode.Replace,
}))
{
#Html.Action("Edit", "StoreItem")
}
</div>
My problems:
The StoreItem controller action is triggered when the parent page loads. I want it to trigger when the dialog is displayed, because it depends on the item that was clicked.
When I close the jQuery Dialog, I want to trigger a post -> the StoreItem's controller action. How do I do this?
While I can't be more accurate about a solution because I'm not sure how the parent view is structured, I'm doing something similar in a project of mine. Here's how I did it:
$('.itemContainer').on('click', '#buttonId', function (event) {
event.preventDefault();
$("#PlaceholderDiv").dialog({
autoOpen: true,
width: 450,
height: 450,
resizable: false,
title: 'Edit Item',
modal: true,
open: function () { //Use the open handler to load data into the dialog.
$('#loadingAnimation').show();
$(this).load('/Controller/Action/' + itemId, function(){$('#loadingAnimation').hide();});
},
close: function () {
$.ajax({
type: "POST",
url: $('#formId').attr('action'),
data: $('#formId').serialize()})
.done(setTimeout(function() {RefreshPartial()}, (delayInms)));
},
buttons: {
Close: function () {
$(this).dialog("close");
}
}
});
return false;
});