pl-jay
pl-jay

Reputation: 1100

Jquery function for dynamic tag creation not working?

After selecting the files with this,

<input type="file" id="myfile1" name="myfile1" data-preview="preview1"
       onchange="readURL(this);" accept="image/*" multiple />

read method should dynamically create the img tag and view the image uploaded,

function readURL(input) {
  if (input.files && input.files.length > 0) {
    var index, reader3, file;

    for (index = 0; index < input.files.length; index++) {
      file = input.files[index];
      console.log(file);
      if (!!file.type.match(/image.*/)) {
        if (window.FileReader) {
          reader3 = new FileReader();
          reader3.onloadend = function (e) {
            $('#floor_plan_preview').append(
              '' +
                '<div class="col-12 ubw-outer">' +
                '<div class="upload-btn-wrapper">' +
                '<button class="btn" style="pointer-events: none;">' +
                '<img src="" alt=""></button>' +
                '<img alt="" id="preview' +
                (index) +
                '" class="preview"></div></div>'
            );
            $('#preview' + (index)).attr('src', e.target.result);
          };
          reader3.readAsDataURL(file);
          console.log(index);
        }
      }
    }
  }
}

But this loops through files array as expected but only renders the img tag with same id at every time.

It seems reader3.onloadend function runs only once how can i fix this ?

Thanks in advance.

Upvotes: 0

Views: 39

Answers (1)

Clarity
Clarity

Reputation: 10873

The issue here is that when onloaded callback is executed, the value of index will always be the last one in the loop. To fix that you can wrap the callback into IIFE (Immediately Invoked Function Expression):

function readURL(input) {
  if (input.files && input.files.length > 0) {
    var index, reader3, file;

    for (index = 0; index < input.files.length; index++) {

      file = input.files[index];
      if (!!file.type.match(/image.*/)) {
        if (window.FileReader) {
          reader3 = new FileReader();
          (function(index) { // wrap the callback into IIFE
            reader3.onloadend = function(e) {
              $('#floor_plan_preview').append(
                '' +
                '<div class="col-12 ubw-outer">' +
                '<div class="upload-btn-wrapper">' +
                '<button class="btn" style="pointer-events: none;">' +
                '<img src="" alt=""></button>' +
                '<img alt="" id="preview' +
                (index + 5) +
                '" class="preview"></div></div>'
              );
              $('#preview' + (index + 5)).attr('src', e.target.result);
            };
          }(index)) // Pass the current index as an arg, so its value is up-to-date
          reader3.readAsDataURL(file);
          console.log(index);
        }
      }
    }
  }
}

Here's a helpful discussion about this issue in general: JavaScript closure inside loops – simple practical example.

Upvotes: 1

Related Questions