2

I'm working on my first web app. It allows users to post events happening in the area, similar to eventbrite. I am using NodeJS, Express, Mongo.

I created a form that allows users to input event details, and upload an image relating to the event.

It looks like the following:

enter image description here

If a user uploads an image then submits, I successfully manage to store the image. When the user wants to view the submitted event, the image appears.

My problem is as follows:

  1. User fills out form and uploads image
  2. User decides he doesn't want an image associated with event
  3. User clicks remove image (image appears to have been removed -- i.e the image preview is gray and says "drop image here or click to upload")
    1. User submits event.
    2. User views event. The "deleted" image is there. In other words, the image never got deleted.

I can't seem to figure out how to actually delete the image once its uploaded.

Here is my EJS File:

<input name="image" type="file" id="image" accept="image/*" style="display:none" 
onchange="handleFiles(this.files)">

 <div id="imageBorder" >
      <div id="imageContainer">
            <div id="dropbox">
                 <i class="fa fa-picture-o" aria-hidden="true"></i>
                 <p> Drop image here or click to upload</p>
            </div>
            <div id="preview" class="hidden">
            </div>
            <button id="fileSelect" class="btn btn-primary btn-block">Upload Image</button>
            <button id="fileRemove" class="btn btn-primary btn-block">Remove Image</button>

        </div>
  </div> <!-- END OF imageBorder -->

Note that I have two divs in imageContainer, a preview div that is hidden, and a dropbox div.

Now here is my .js file:

function eventImageSetup() {
    var dropbox = document.getElementById("dropbox"),
        fileElem = document.getElementById("image"),
        fileSelect = document.getElementById("fileSelect"),
        fileRemove = document.getElementById("fileRemove");
    $(dropbox).height($('#imageBorder').height());
    fileSelect.addEventListener("click", function(e) {
        if (fileElem) {
          fileElem.click();
          e.preventDefault(); // to prevent submit
        }
    }, false);
    fileRemove.addEventListener("click", function(e) {
        e.preventDefault(); // prevent submit
        if(!$('#preview').hasClass('hidden')) { // If there is an image uploaded
            $('#preview').empty(); 
            $('#dropbox').removeClass('hidden');
            $('#preview').addClass('hidden');
            $('#fileSelect').text('Upload Image');
        }
        removeError($('#imageError'), $('#image'));
    });
    dropbox.addEventListener("dragenter", dragenter, false);
    dropbox.addEventListener("dragover", dragover, false);
    dropbox.addEventListener("drop", drop, false);
}
....
....
function handleFiles(files) { 
    var file = files[0];
    ... //some code for error checking here - deleted it for now 
    var img = document.createElement("img");
    img.id = "uploadedImage";
    img.file = file;
    img.onload = function() {
         adjustImageSize(img);
    };

    $('#dropbox').addClass('hidden');
    $('#preview').removeClass('hidden');
    $('#preview').empty();
    $('#preview').append(img);
    $('#fileSelect').text('Replace Image');

    var reader = new FileReader();
    reader.onload = (function(aImg) {
       return function(e) {
           aImg.src = e.target.result;
       };
    })(img);
    reader.readAsDataURL(file);
}

Basically, on the front-end, when a user uploads an image, an image tag is created and inserted into preview. The class 'hidden' is removed from preview, and the class 'hidden' is added to dropbox. Hence the image appears.

When delete image is clicked, is deleted from preview, preview is hidden, and the class 'hidden' is removed from dropbox. I.e, it appears that the image has been removed.

HOWEVER, once the form is submitted, req.file is NOT empty.

This is part of the routes node file (I'm using multer for uploading images -- irrelevant)

router.post("/", middleware.isLoggedIn, upload.single('image'), function(req,res) { 

    var filepath = undefined;
    if(req.file) { // THIS IS TRUE... REQ.FILE is not empty....
        filepath = req.file.path.substr(7); // Substr to remove "/public"
    }  
    ....
    ....
}

Does anyone have any suggestions? I'd like to actually understand what is going on when I say reader.readDataAsURL (I think this is whats saving the file???) I've read a few stackoverflow posts, but couldn't quite understand the suggested solutions or explanations...

Asool
  • 13,031
  • 7
  • 35
  • 49

2 Answers2

1

Selecting an image will just show it in the browser but not actually upload it. That only happens after the form is submitted. And according to your code, after the user has clicked the "Remove image" button, the <input type="file" /> remains unchanged, thus sending the form will still upload the image. You need to actually clear the field as described here: Clearing <input type='file' /> using jQuery

As for the technically unrelated second issue:

I can't seem to figure out how to actually delete the image once its uploaded.

In order to delete the image after it is uploaded, presumably in "edit event" mode, you have to send along form data indicating that the image is supposed to be deleted, then delete it on the server.

Community
  • 1
  • 1
0

As per Chris G's answer, this is what I did, and it worked:

 fileRemove.addEventListener("click", function(e) {
    e.preventDefault(); // prevent submit
    if(!$('#preview').hasClass('hidden')) { // If there is an image uploaded
        $('#preview').empty(); 
        $('#dropbox').removeClass('hidden');
        $('#preview').addClass('hidden');
        $('#fileSelect').text('Upload Image');
        $('#image').wrap('<form>').closest('form').get(0).reset();
         $('#image').unwrap();
    }
    removeError($('#imageError'), $('#image'));
});
Asool
  • 13,031
  • 7
  • 35
  • 49