Search code examples
javascriptjqueryimagepreview

Custom preview images using FileReader js


I need to create custom preview the selected images. I have seen several answers about doing this and they do it by creating an img element and using appendTo to place them in a specific div. I have done this successfully as shown below in a jquery "change event"

 $(document).on("change", "#file", function() {
    var countFiles = $(this)[0].files.length;
    var imgPreview = $("#img-preview");

    for (var i = 0; i < countFiles; i++) {
       var reader = new FileReader();
       reader.onload = function (e) {
         $("<img />", {
              "src": e.target.result,
              "class": "img-thumbnail"
         }).appendTo(imgPreview);
    }
    reader.readAsDataURL($(this)[0].files[i]);
  }
});

The problem I have is to preview the images with the following structure:

IMAGE

Here the custom structure with bootstrap

<div class="container">
    <div class="row">
        <div class="col-md-12">
            <div class="wraper-foto-grande d-flex justify-content-center">
                <img class="img-fluid d-flex align-items-center" src="img1.jpg">
            </div>
        </div>
    </div>
</div>
<div class="container">
    <div class="row">
        <div class="col-md-4">
            <div class="wrapper-thumb d-flex justify-content-center">
                <img class="img-fluid d-flex align-items-center" src="img2.jpg">
            </div>
        </div>
        <div class="col-md-4">
            <div  class="wrapper-thumb d-flex justify-content-center">
                <img class="img-fluid d-flex align-items-center" src="img3.jpg">
            </div>
        </div>
        <div class="col-md-4">
            <div class="wrapper-thumb d-flex justify-content-center">
                <img class="img-fluid d-flex align-items-center" src="img4.jpg">
            </div>
        </div>      
    </div>
</div> 

I have tried to create an array with the target.result to later use it in a function and create the structure mentioned above but I have the problem that the created array is empty. I have also seen several answers on this topic but I have not succeeded in creating the preview.

Here code:

$(document).on("change", "#file", function() {
  var countFiles = $(this)[0].files.length;
  var imgPreview = $("#img-preview");
  var imagesArray = [];

  for (var i = 0; i < countFiles; i++) {
      var reader = new FileReader();
      reader.onload = function (e) {
          imagesArray.push(e.target.result);
      }
     reader.readAsDataURL($(this)[0].files[i]);
  }
  console.log(imagesArray.length); //show 0
  console.log(imagesArray); // guess select 4 images, show 4 elements inside but I cannot access
});

My idea was to use imagesArray in a function to create the custom structure with bootstrap but I don't have access to any element.

Thanks for your help.


Solution

  • 1st: Check if more than 1 images selected then conditionally set [col-12] class for first preview and rest of set [col-4] class & before image append in result div(#imageResults) should be empty like $('#imageResults').html('');.

    2nd: Check inline condition like i==0?'12':'4'.

    Note: I added border class in image parent div for testing purpose only.

    $(document).on("change", "#file", function() {
      var countFiles = $(this)[0].files.length;
      //Result div empty before appending new selected image 
      $('#imageResults').html(''); 
      for (var i = 0; i < countFiles; i++) {
        //`const columnSet` for full col-12 or col-4 class
        const columnSet = (i==0?'12':'4');
        var reader = new FileReader();
        reader.onload = function (e) {
          // Append image preview divs
          $('#imageResults').append(`<div class="mb-3 col-`+columnSet+`">
            <div class="border d-flex justify-content-center">
              <img class="img-fluid d-flex align-items-center" src="`+e.target.result+`">
            </div>
          </div>`);
        }
        reader.readAsDataURL($(this)[0].files[i]);
      }
    });
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    
    <div class="container my-3">
      <div class="row">
        <div class="col-md-12">
          <div class="input-group mb-3">
            <label class="custom-file">
              <input type="file" class="custom-file-input" id="file" accept="image/*" multiple="multiple">
              <span class="custom-file-label">Choose multiple image</span>
            </label>
          </div>
        </div>
      </div>
      <!-- Image Preview Area -->
      <div class="row" id="imageResults">
      </div>
    </div>