skip to Main Content

I’m trying to wrap a set of images in a div every two loops. Such that every two bootstrap columns are in individual rows. e.g.

<div class="row">
  <div class="col-6"><img src=".."></div>
  <div class="col-6"><img src=".."></div>
</div>

As you can see by this example below, it appears to work when using text.

var data = ["https://via.placeholder.com/100",
  "https://via.placeholder.com/100",
  "https://via.placeholder.com/100",
  "https://via.placeholder.com/100"
];

var output = $('.container');
var i = 0;
$.each(data, function(index, value) {
  var template = '<div class="col-6"><img src=' + value + '></div>';
  if (i % 2 == 0) {
    output.append('<p>ROW START</p.')
  }
  output.append(template)
  i++;
  if (i % 2 == 0) {
    output.append('<p>ROW END</p>')
  }
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"></div>

However, when I use actual divs, they self close automatically resulting in a structure like:

<div class="container">

    <div class="row"></div>

    <div class="col-6"><img src="https://via.placeholder.com/100"></div>
    <div class="col-6"><img src="https://via.placeholder.com/100"></div>

    <div class="row"></div>

    <div class="col-6"><img src="https://via.placeholder.com/100"></div>
    <div class="col-6"><img src="https://via.placeholder.com/100"></div>
</div>

Example snippet:

var data = ["https://via.placeholder.com/100",
  "https://via.placeholder.com/100",
  "https://via.placeholder.com/100",
  "https://via.placeholder.com/100"
];

var output = $('.container');
var i = 0;
$.each(data, function(index, value) {
  var template = '<div class="col-6"><img src=' + value + '></div>';
  if (i % 2 == 0) {
    output.append('<div class="row">')
  }
  output.append(template)
  i++;
  if (i % 2 == 0) {
    output.append('</div>')
  }
})
.row {
min-height:1px;
background:blue;
}

.col-6 {
background:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
 <div class="container"></div>

Why do the div tags self close, how can I fix this?

3

Answers


  1. The DOM is not a string of HTML, so you don’t piece together tags that are individually inserted. If you’re going to build DOM elements from HTML strings, you need to build the entire element before it’s appended. If you try to do it in pieces, a missing closing tag will be automatically corrected, and a lone closing tag will be ignored as invalid input.

    Instead, prebuild the entire string, and append it once complete.

    var data = ["https://via.placeholder.com/100",
      "https://via.placeholder.com/100",
      "https://via.placeholder.com/100",
      "https://via.placeholder.com/100"
    ];
    
    var html = data.reduce(function(res, value, i) {
      return res +
        (i % 2 === 0 ? '<div class="row">' : "") +
        ('<div class="col-6"><img src=' + value + '></div>') +
        (i % 2 !== 0 ? '</div>' : "");
    }, "");
    
    $('.container').append(html);
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="container">
      <div>

    This solution uses .reduce(), since it’s built into JS, and designed for this very purpose. The remaining jQuery can be easily eliminated too, taking you a step closer to being free from unnecessary abstraction.

    Login or Signup to reply.
  2. Prepare (build) string content and then append to your output. Something like this.

    var data = ["https://via.placeholder.com/100",
      "https://via.placeholder.com/100",
      "https://via.placeholder.com/100",
      "https://via.placeholder.com/100"
    ];
    
    var output = $('.container');
    var i = 0;
    var content = '';
    
    $.each(data, function(index, value) {
      var template = '<div class="col-6"><img src=' + value + '></div>';
      if (i % 2 == 0) {
        content += '<div class="row">';
      }
      content += template;
      i++;
      if (i % 2 == 0) {
        content += '</div>';
      }
    })
    output.append(content);
    .row {
      min-height: 1px;
      background: blue;
    }
    
    .col-6 {
      background: red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
    <div class="container"></div>
    Login or Signup to reply.
  3. $.each(data, function(index, value) {
      var template = '<div class="col-6"><img src=' + value + '/></div>';
      if (i % 2 == 0) {
        output.append('<div class="row"></div>')
      }
      $(".row").last().append(template)
      i++;
    })
    

    Just append template to the last added row.

    https://jsfiddle.net/zL5phyfq/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search