Clear upload area in Vue2-Dropzone - javascript

I'm currently working on Laravel Vue SPA admin panel. And I've applied Vue2-Dropzone to upload images for the gallery section.
In this project the vue2-dropzone form opens on a bootstrap model.
My codes successfully uploads the images. When I close the model and reopen it to upload other images it shows the thumbnails of previously uploaded images.
Below is my code snippet:
import vue2Dropzone from "vue2-dropzone";
import "vue2-dropzone/dist/vue2Dropzone.min.css";
export default {
data() {
return {
dropzoneOptions: {
url: "/api/carousel",
maxFilesize: 10,
acceptedFiles: '.jpg, .jpeg',
dictDefaultMessage: "Click or Drag and Drop to upload",
headers: {
"X-CSRF-TOKEN": document.head.querySelector("[name=csrf-token]")
.content
}
}
};
},
methods: {
newModal() {
vue2Dropzone.removeAllFiles(true);
$("#addNew").modal("show");
}
},
components: {
vueDropzone: vue2Dropzone
}
};
With the above code I get the following error after clicking the add image button that opens the model to upload images:
app.js:84606 Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_0_vue2_dropzone___default.a.removeAllFiles is not a function
at VueComponent.newModal (app.js:84606)
at invoker (app.js:54930)
at HTMLButtonElement.fn._withTask.fn._withTask (app.js:54729)
I want to clear the thumbnails of previously uploaded images from dropzone modal.
Can anyone help me out on this ?

Assume you have vue-dropzone with ref in template
<vue-dropzone ref="myVueDropzone" id="dropzone">
</vue-dropzone>
then you should use
this.$refs.myVueDropzone.removeAllFiles()

The removeAllFiles() is kind of a hack. It won't work for some cases.
For example, it will not 'reset' the Dropzones' options object. So if you want to do validations for diferent cases via the options object, it will not reset with the removeAllFiles() method.
The right way to reset the Dropzone (or any Vue object in that matter) is to set and change the :key attribute. Like this for example:
<vue-dropzone :key="`dropzone-${dynamicVariableOrJustSomeCounter}`">
</vue-dropzone>

Related

Why does my script not run on AJAX refresh?

I'm working on an avatar uploader for my project. Everything has been so far so good, and this morning I had no issues. A little while later, BOOM. Death and destruction. Very sadness.
When I first choose a file, it pops up the crop tool immediately, and works fine. If I attempt to upload a different file, the crop tool disappears and not even a preview of the image is presented.
How does my system work? I'm using the Laravel framework as my backend, and the Laravel Livewire package for front-end functionality. Livewire allows me to write Vue-like components in PHP.
Here's the form I'm working on. It's also the component that's refreshed every time that Livewire sees a new file in the input.
<label for="image-upload">
<div class="w-full mt-4 button"><i class="far fa-fw fa-upload"></i> Drag and drop, or <b>browse</b></div>
</label>
<input id="image-upload" type="file" wire:model="image" class="hidden" accept="image/png, image/gif, image/jpeg">
#if($image)
<div id="avatar-preview" class="w-full" style="height: 300px;"></div>
<script>
new Croppie(document.querySelector('#avatar-preview'), {
viewport: { width: 200, height: 200, type: 'circle' },
enforceBoundary: true,
}).bind('{!! $image->temporaryUrl() !!}');
</script>
<button type="submit" class="w-full mt-16 button is-green">Submit new avatar</button>
#endif
I'm using the Croppie JS package for the crop tool. It requires that I either pass it an img element it'll attach to, or a container to fit into. I picked a container so I could control the size of the crop tool. When I upload an image to the input, Livewire will take the image, validate it's an image and doesn't pass a certain size, and uploads the image to a temporary directory. The $image->temporaryUrl() echoes the path to that temporary file. When the file upload is done and the temporary image is ready, Livewire refreshes just the component via AJAX. At this point, I attempt to create a new Croppie instance, attach it to my preview container, and bind the temporary image to it.
This works on the first file upload! Then, when I attempt to change the file (as a user might) the entire instance disappears. I attempted to check and see if it was an issue instantiating Croppie again, since in my mind if the component is refreshed, creating a new instance of the tool shouldn't be an issue.
<script>
if (typeof crop === 'undefined') {
console.log('crop undefined');
let crop = new Croppie(document.querySelector('#avatar-preview'), {
viewport: { width: 200, height: 200, type: 'circle' },
enforceBoundary: true,
}).bind('{!! $image->temporaryUrl() !!}');
} else {
console.log('crop defined');
crop.bind('{!! $image->temporaryUrl() !!}');
}
console.log('crop finished');
</script>
And the 'undefined' and 'finished' logs come in on the first upload, but nothing happens on the refresh.
So I also tested just doing this...
#if($image)
<img src="{{ $image->temporaryUrl() }}">
#endif
To ensure at the very least that the preview was working correctly, and lo and behold it does!
The big problem is that even when the Croppie doesn't refresh, no errors or warnings occur. It just doesn't seem to execute what's in the <script> tag at all.
Any tips or advice?
After further reading, it appears Livewire can, from the component class, emit "events" that can be picked up by JavaScript. My issue was caused by the natural behavior of changing DOM content by .innerHtml.
In my component class, in the updated() function that handles what to do when the input is updated, I added
$this->emit('avatar_preview_updated', $this->image->temporaryUrl());
I then added this listener to my page's global JS:
livewire.on('avatar_preview_updated', image => {
new Croppie(document.querySelector('#avatar-preview'), {
url: image,
viewport: { width: 200, height: 200, type: 'circle' },
boundary: { height: 300 },
enforceBoundary: true,
});
});
Which produces the desired result.

How Can I Pass String Variable to Anonymous Adobe View SDK Script?

I have a very basic knowledge of javascript and I have been unable to find a solution for my specific use of the Adobe View SDK API, though it seems like there should be a way. I am working on a web page to show newsletters in the pdf viewer. I have created a w3.css modal element so that I can open the viewer with a button click, and then close it with an "x" in the corner. The button click and the "x" toggle between the display style being "none" or "block". I really like this solution as it lets me use small images of the newsletters as the buttons, and it can be observed here: Test News Page by clicking on the newsletter image below May 4, 2020.
The ultimate goal I have is to be able to change the name of the pdf document that is opened in the viewer by clicking the button, which would need to pass a string variable called "docName" to the url called by the View SDK script. Since the url is already specified in the script inside my modal element when the page loads, here is the thinking I have for the additional script I need to pass my string variables: The button-click invokes my script (function changeName(docName)) and passes the "docName" variable. Then my script needs to pass this variable to the url in the View script (this is the part I don't know how to do), then refresh the page to reload my modal, and then change the display style of the modal to "block". I will copy the code for the View SDK below, showing where I need to insert the string variable with my document name:
<script src="https://documentcloud.adobe.com/view-sdk/main.js"></script>
<script type="text/javascript">
document.addEventListener("adobe_dc_view_sdk.ready", function(){
var adobeDCView = new AdobeDC.View({clientId: "06179511ab964c9284f1b0887eca1b46", divId: "adobe-dc-view"});
adobeDCView.previewFile({
content:{location: {url: "https://www.shcsfarmington.org/" + docName + ".pdf"}},
metaData:{fileName: "Newsletter_050420.pdf"}
}, {embedMode: "FULL_WINDOW", defaultViewMode: "FIT_WIDTH"});
});
</script>
It seems like this should work, but with my limited knowledge of javascript I don't know how to pass this variable to the anonymous function in the View SDK code, and I would need as much detail and specifics in the syntax of the solution. I appreciate any help with this. Thanks.
EDIT: I thought maybe it would help to show the code for the function that I have come up with so far - then it could be examined and easier to debug and comment on:
<button id="CSS-050420" onclick="changeDoc('Newsletter_050420');"></button>
<script>
function changeDoc(docName) {
/* Need to pass docName to url=https://shcsfarmington.org/2020/news/Newsletter_" + newsDate + ".pdf"; */
window.location.reload(true);
document.getElementById('viewerModal').style.display='block';
}
</script>
I created a CodePen here for you to look at.
Basically, you'll load the first file when the SDK is ready but then you need to set the adobeDCView to null before recreating it.
function showPDF(url) {
adobeDCView = null;
fetch(url)
.then((res) => res.blob())
.then((blob) => {
adobeDCView = new AdobeDC.View({
// This clientId can be used for any CodePen example
clientId: "e800d12fc12c4d60960778b2bc4370af",
// The id of the container for the PDF Viewer
divId: "adobe-dc-view"
});
adobeDCView.previewFile(
{
content: { promise: Promise.resolve(blob.arrayBuffer()) },
metaData: { fileName: url.split("/").slice(-1)[0] }
},
{
embedMode: "FULL_WINDOW",
defaultViewMode: "FIT_PAGE",
showDownloadPDF: true,
showPrintPDF: true,
showLeftHandPanel: false,
showAnnotationTools: false
}
);
});
}
The link click even will pass the url to the PDF and then display it.

Kony: import image from phone to app

I'm making an android and ios app using kony and I want to be able to import an image from the phone's library (jpeg or png).
I have the function for my import button here:
this.control("btnImportPicture").onClick = function (button) {
// Insert solution here
};
The name of my image widget (which I want to set to the selected image) is imgUser
Problem is I have no idea what to do for my btnImportPicture button onClick function
Edit:
I have seen that you can use the following in the onClick function:
var config = {
selectMultipleFiles: false,
filter: ["image/png", "image/jpeg"]
};
kony.io.FileSystem.browse(config, selectedFileCallback);
But I have no idea what to do for the selectedFileCallback, currently it just crashes everytime I click the button.
I got an answer on the kony forums and thought I better share it here in-case anyone else runs into this issue.
kony.io.FileSystem.browse API is applicable for only Desktopweb Platform. it will not work in Mobile richclient applications.
we can use "kony.phone.openMediaGallery" API. The main usecase of this API is to open the gallery of the phone and to pick any image. Once we select any image then onselectioncallback function will trigger with image rawBytes as input parameter . we can use this rawBytes in our Application either to display image on the image Widget or for other usecases
Please refer below documentation link.
http://docs.kony.com/konylibrary/studio/kony_studio_api_reference_guide/Default.htm#phone.htm#phone.op
Put this in your onClick:
function openGallery()
{
var querycontext = {mimetype:"image/*"};
var returnStatus = kony.phone.openMediaGallery(onselectioncallback, querycontext);
}
function onselectioncallback(rawbytes)
{
if (rawbytes == null)
{
alert("Please select an Image");
return;
}
frmone.image26850851102837.rawBytes=rawbytes;
}
Note : we can select only one image at a time.

filepicker-rails w/signup form: button to `remove` the file in Filepicker

In my Rails 3.2 app I am using Filepicker through the filepicker-rails gem to allow users to upload a profile photo on the signup form. In the f.filepicker_field I am using the onchange option to call an onImageUpload() function that gets information about the newly uploaded image from the automatically-generated event.fpfile and disables the Filepicker browse button:
function onImageUpload() {
file = event.fpfile
img = $("<img>").prop("src", file.url).css({
width: '160px',
height: '160px',
});
$("#profile_photo_preview").append(img);
$(".filepicker-button").toggleClass("disabled");
};
I read about the event.fpfile at the Filepicker docs section on Widgets. In the form I also have a link that, when clicked, removes the recently updated image from the DOM and re-enables the Filepicker button:
:javascript
$(document).ready(function() {
$("#picture-remover").click(function() {
$("#profile_photo_preview").html("");
if ( $(".filepicker-button").hasClass("disabled") ) {
$(".filepicker-button").toggleClass("disabled");
};
});
});
...
...
= link_to "Remove Picture", id: "picture-remover"
This all seems to work pretty well. The only problem is that if a user removes the first picture and then uses the Filepicker browser to upload another, the original picture is still being saved in my Filepicker account.
I'd like to have my "Remove Picture" link remove the picture not only from the DOM, but also from my Filepicker account altogether. The Filepicker docs have a section on removing/deleting files here but I don't really understand the example code or how to implement it for myself. I'm particularly confused about the relationship between the InkBlob that is mentioned for removing a file and the event.fpfile object that I'm using to display a thumbnail preview.
So far I've tried adding the following line to my "Remove Picture" link but nothing happens:
:javascript
$(document).ready(function() {
$("#picture-remover").click(function() {
$("#profile_photo_preview").html("");
if ( $(".filepicker-button").hasClass("disabled") ) {
$(".filepicker-button").toggleClass("disabled");
};
filepicker.remove(InkBlob); #added this line
});
});
Many thanks to anyone who can point me in the right direction!
InkBlob and event.fpfile objects have the same role and the same attributes.
In your example you can pass event.fpfile object to remove function.
var file = event.fpfile;
filepicker.remove(
file,
function(){
console.log("Removed");
}
);
Generally to remove filepicker file you only need it's url.
So this code also works fine:
var someObject = {url: 'https://www.filepicker.io/api/file/xaXphhT9R0GB1tPYUQAr'};
filepicker.remove(
someObject,
function(){
console.log("Removed");
}
);

How to display cancel button for failed uploads in fineuploader?

I am using fineuploader. Some upload may fail as user try to upload duplicate file.
I see a red color and the error message from server is shown.
I am not seeing any cancel OR Remove button that would allow the user to start fresh again by selecting a new file.
I was expecting fineuploader to show cancel button on failed files but it is not.
I can add onError callback then find the right row and show the cancel or other button by adding Remove button. That sound messy solution.
That cancel button would remove that file and let user select another file.
Can I add this capability by setting options in the settings?
var fileUploader = new qq.FineUploader({
element: $('#manual-fine-uploader')[0],
request: {
endpoint: 'upload/UploadFiles',
},
multiple: true,
autoUpload: false,
validation: {},
text: {uploadButton: '<i class="icon-plus icon-white"></i> Select File'},
callbacks: {
onSubmit: function (id, file) {//my custom code },
onCancel: function(id, file){ if(filesCount>=1) filesCount--;},
onComplete: function (id, fileName, responseJSON) {filesCount--;}
},
failedUploadTextDisplay: {
mode: 'custom',
maxChars: 40,
responseProperty: 'error',
enableTooltip: true
}
});
Thanks
Fine Uploader only displays a cancel button while a file is uploading (as well before uploads have started if you have set the autoUpload option to false). Showing a cancel button after the upload has completed seems like it would be a bit confusing to users, but I can see why you might want to display a "remove" button.
You can easily do this by adding the button to the file portion of your template. For example, your template might look similar to this:
<div class="qq-uploader-selector qq-uploader">
...
<ul class="qq-upload-list-selector qq-upload-list">
<li>
...
<button class="remove-button-selector" style="display:none">Remove</button>
</li>
</ul>
</div>
Then, add a click handler to purge the file from Fine Uploader's internals & the UI:
$('#manual-fine-uploader').on("click", ".remove-button-selector", function() {
var fileId = fileUploader.getId(this);
fileUploader.cancel(fileId);
});
Finally, in your onComplete handler, show the button if the upload has failed:
onComplete: function(id, name, response, xhr) {
var fileItemEl = fileUploader.getItemByFileId(id);
if (!response.success) {
$(fileItemEl).find(".remove-button-selector").show();
}
}
Additionally, since you are already using jQuery in your project, I strongly suggest you make use of the Fine Uploader jQuery plug-in. It will make your life a bit easier.

Categories