1

I have an array of companies:

var list = ["company1", "company2", "company3", "company4", "company5", "company6"];

And I want to loop through the array and append a list of companies to the dom in groups of three. Like this:

<div class="row">
    <div class="col col-4">Company 1</div>
    <div class="col col-4">Company 2</div>
    <div class="col col-4">Company 3</div>
</div>
<div class="row">
    <div class="col col-4">Company 4</div>
    <div class="col col-4">Company 5</div>
    <div class="col col-4">Company 6</div>
</div>
<div class="row">
    <div class="col col-4">Company 7</div>
    <div class="col col-4">Company 8</div>
    <div class="col col-4">Company 9</div>
</div>

^ so this would be the ideal markup - that gets generated after the array is looped. Ideally I want to create an empty markup template - then read from that template then create markup in the js

My code:

var list = ["company1", "company2", "company3", "company4", "company5", "company6"];

var itemWrapper = $('.wrapper');
var itemRow = itemWrapper.find('.row');
var itemCol = itemRow.find('.col').eq(0);

console.log("itemRow", itemRow);
console.log("itemCol", itemCol);

itemWrapper.empty();
$.each(list, function(index, value) {
  console.log("index", index);
  console.log("value", value);
  
  if (index % 3 == 0) {
   console.log("-------new row");
   $('.wrapper').append('<div class="row">');
  }
  
  $('.wrapper').append(itemCol.html(value));
  
  if (index % 3 == 0) {
   //$('.wrapper').append('</div>');
   console.log("-------end row");
  }
  
});

/*
if (index % 3 == 0) {
  console.log("new row");
  modalWindow.partyContainer.append('<div class="row party-list">');
}
console.log("modalWindow.itemRow", modalWindow.itemRow);
var itemCol = $(modalWindow.itemRow).html(value.name);
modalWindow.partyContainer.append(itemCol);
if (index + 3 % 3 == 0) {
  console.log("end row");
  modalWindow.partyContainer.append('</div>');
}
if (index == 12) {
  return false;
}
*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
    <div class="row">
        <div class="col col-4">x</div>
        <div class="col col-4">c</div>
        <div class="col col-4">v</div>
    </div>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
The Old County
  • 89
  • 13
  • 59
  • 129
  • You can [split the array into chunks](https://stackoverflow.com/questions/8495687/split-array-into-chunks) of 3 and loop through it. – sabithpocker May 02 '18 at 16:17
  • The issue that you are running into, it appears, is that you are trying to treat appending to the dom as if you are creating markup. You are not. When you append elements to the dom, you are creating document elements. There is no opening or closing tag on an element. It's just an object. HTML is used as a descriptive language to tell the browser where an element starts and stops. When you are appending directly to the dom, you cannot break up these statements. If you append '
    ', it will create the div element. It doesn't wait/need the closing
    – Taplar May 02 '18 at 16:17
  • - so append the head/tail as a var? – The Old County May 02 '18 at 16:21

5 Answers5

0

Simply append a new row using jQuery if the remainder is 0 and add <div>s accordingly.

var list = ["company1", "company2", "company3", "company4", "company5", "company6"];

var itemWrapper = $('.wrapper');
itemWrapper.empty();

list.forEach(function(row, idx) {
 if(!(idx % 3)) {
   itemWrapper.append('<div class="row"></div');
  }
  var itemRow = $('.wrapper .row:last-child');
  itemRow.append('<div class="col col-4">'+row+'</div>');
});
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>

<div class="wrapper">

</div>

Let me know if you have any questions. Hope this helps.

Shashank
  • 5,570
  • 1
  • 11
  • 17
0

Just use a variable $row that will hold the current row element. Update that variable for each three elements with a new row element. And for each element, just append to the $row:

var list = ["company1", "company2", "company3", "company4", "company5", "company6", "company7"];

var $wrapper = $('.wrapper');
$wrapper.empty();

var $row;                                                      // the current row of elements
$.each(list, function(index, value) {
  if(index % 3 == 0) {                                         // for every three elements
    $row = $('<div class="row"></div>').appendTo($wrapper);    // create a new row element and assign it to $row
  }
    
  $row.append('<div class="col col-4">' + value + '</div>');   // add the current element to the current row
});
.row { margin: 10px 0; background: #eee; }

.row > * { display: inline-block; margin: 0 10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper"></div>
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
0

You can use array.slice to split the array for you and iterate over the chunks as in my example.

Is there a particular reason you want to use the existing HTML as a template?

var list = ["company1", "company2", "company3", "company4", "company5", "company6", "company7", "company8", "company9", "company10"];

var itemWrapper = $('.wrapper');

var listChunks = [];
var chunkSize = 3;
for (var i = 0; i < list.length; i += chunkSize) {
    listChunks.push(list.slice(i,i+chunkSize));
}

itemWrapper.empty();
var rowHtmlOpen = '<div class="row">';
var rowHtmlClose = '</div>';
listChunks.forEach(function (chunk) {
    var rowHtml = rowHtmlOpen;
    chunk.forEach(function (col) {
        rowHtml += '<div class="col col-4">' + col + '</div>'
    });
    rowHtml += rowHtmlClose;
    itemWrapper.append(rowHtml);
});
.row { margin: 10px 0; background: #ffe; }
.row > * { display: inline-block; margin: 0 10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper"></div>
Jim Wright
  • 5,905
  • 1
  • 15
  • 34
0
var list = ["company1", "company2", "company3", "company4", "company5", "company6"];
var wrapper = $('.wrapper');
var row = {};
$.each(list,function(key,val){
    if((key % 3) == 0){
        row = $('<div>', {'class' : 'row'});
        wrapper.append(row);
    }
    var col = $('<div>', {'class' : 'col col-4'});
    col.text(val);
    row.append(col);
});
iXs
  • 726
  • 5
  • 4
0

Here is a version that uses just javascript. The logic gets the column and removes it from the DOM, so that it's text can be changed without effecting the DOM every time. It then builds a string with the html desired to take the place of the contents of the wrapper. At the very end it replaces the contents of the wrapper with the whole result. Building the html, rather than elements, removes some overhead, and changing the wrapper at the very end limits the number of times the DOM is changed, both of which are performance gains.

EDIT: Made a small modification. I added an additional company name so the array is not evenly divisible by 3, and then I modified the closing logic to add the if the element is the last one, regardless, so the html is always properly closed.

var list = ["company1", "company2", "company3",
            "company4", "company5", "company6",
            "company7"];

var itemWrapper = document.querySelector('.wrapper');
var itemColumn = itemWrapper.querySelector('.col');
var output = '';

itemColumn.parentNode.removeChild(itemColumn);

list.forEach(function(company, index){
  if (index % 3 === 0) output += '<div class="row">';
  
  itemColumn.innerText = company;
  output += itemColumn.outerHTML;
  
  if (++index % 3 === 0 || index === list.length) output += '</div>';
});

itemWrapper.innerHTML = output;
<div class="wrapper">
    <div class="row">
        <div class="col col-4">x</div>
        <div class="col col-4">c</div>
        <div class="col col-4">v</div>
    </div>
</div>
Taplar
  • 24,788
  • 4
  • 22
  • 35