0

I have a table. I want to add rowspan to the first td of each row. But when I do that, it is messing up the table and pushing my data in the table to right.

This is my code:

let data = [
  {device: 'iphone',   site: 'google', val1:10, val2:20, val3:30},
  {device: 'iphone',  site: 'bing', val1:23, val2:12, val3:14},
  {device: 'iphone',  site: 'jeeves', val1:67, val2:78, val3:12},
  {device: 'ipad',  site: 'google', val1:10, val2:20, val3:30},
  {device: 'ipad',  site: 'bing', val1:23, val2:12, val3:14},
  {device: 'ipad',  site: 'jeeves', val1:67, val2:78, val3:12},
  {device: 'mac',   site: 'google', val1:10, val2:20, val3:30},
  {device: 'mac',   site: 'bing', val1:23, val2:12, val3:14},
  {device: 'mac',   site: 'jeeves', val1:67, val2:78, val3:15}  
]

let heads = Object.keys(data[0]);
heads.forEach(d => $(`#headers`).append(`<th>${d}</th>`));

data.forEach(td => {
  $(`#body_deets`).append(`<tr></tr>`);
  heads.forEach(th => {
    $(`#body_deets > tr:last`).append(`<td>${td[th]}</td>`);
  });
});

$(`#body_deets > tr > td:first-child`).each(function() {
    $(this).attr('rowspan', '3');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table class='table' border=1>
  <thead><tr id='headers'></tr></thead>
    <tbody id='body_deets'></tbody>
</table>

As you can see, this is adding the rowspan and pushing a lot of my data to the right.

How can I get my table to look like this:

table with rowspan

Is there a way to do this using jQuery?

3 Answers 3

1

Assuming you want to combine every three cells into a single cell, you need to set the rowspan on the first of the three cells, then remove the next two:

let data = [{
    device: 'iphone',
    site: 'google',
    val1: 10,
    val2: 20,
    val3: 30
  },
  {
    device: 'iphone',
    site: 'bing',
    val1: 23,
    val2: 12,
    val3: 14
  },
  {
    device: 'iphone',
    site: 'jeeves',
    val1: 67,
    val2: 78,
    val3: 12
  },
  {
    device: 'ipad',
    site: 'google',
    val1: 10,
    val2: 20,
    val3: 30
  },
  {
    device: 'ipad',
    site: 'bing',
    val1: 23,
    val2: 12,
    val3: 14
  },
  {
    device: 'ipad',
    site: 'jeeves',
    val1: 67,
    val2: 78,
    val3: 12
  },
  {
    device: 'mac',
    site: 'google',
    val1: 10,
    val2: 20,
    val3: 30
  },
  {
    device: 'mac',
    site: 'bing',
    val1: 23,
    val2: 12,
    val3: 14
  },
  {
    device: 'mac',
    site: 'jeeves',
    val1: 67,
    val2: 78,
    val3: 15
  }
]

let heads = Object.keys(data[0]);
heads.forEach(d => $(`#headers`).append(`<th>${d}</th>`));

data.forEach(td => {
  $(`#body_deets`).append(`<tr></tr>`);
  heads.forEach(th => {
    $(`#body_deets > tr:last`).append(`<td>${td[th]}</td>`);
  });
});

$(`#body_deets > tr > td:first-child`).each(function(index) {
  if(index % 3 == 0) {
    $(this).attr('rowspan','3');
  } else {
    $(this).remove();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table class='table' border=1>
  <thead>
    <tr id='headers'></tr>
  </thead>
  <tbody id='body_deets'></tbody>
</table>

Sign up to request clarification or add additional context in comments.

Comments

1

For the colspan elements, you need only 1 <td>. Just remove the extras like this:

$(`#body_deets > tr > td:first-child`).each(function(index,elem) {
        if (index%3!=0) $(this).remove();
         else $(this).attr('rowspan', '3');
    });

Comments

1

I would calculate the index ranges ahead of time. See the indexRange function and the rowSpan assignment.

{
  "iphone": { "first": 0 , "last": 2 },
  "ipad":   { "first": 3 , "last": 5 },
  "mac":    { "first": 6 , "last": 8 }
}

const data = [
  { device: 'iphone' , site: 'google' , val1: 10 , val2: 20, val3: 30 },
  { device: 'iphone' , site: 'bing'   , val1: 23 , val2: 12, val3: 14 },
  { device: 'iphone' , site: 'jeeves' , val1: 67 , val2: 78, val3: 12 },
  { device: 'ipad'   , site: 'google' , val1: 10 , val2: 20, val3: 30 },
  { device: 'ipad'   , site: 'bing'   , val1: 23 , val2: 12, val3: 14 },
  { device: 'ipad'   , site: 'jeeves' , val1: 67 , val2: 78, val3: 12 },
  { device: 'mac'    , site: 'google' , val1: 10 , val2: 20, val3: 30 },
  { device: 'mac'    , site: 'bing'   , val1: 23 , val2: 12, val3: 14 },
  { device: 'mac'    , site: 'jeeves' , val1: 67 , val2: 78, val3: 15 }  
 ]; 

let fields =  Object.keys(data[0]);
fields.forEach(d => $(`#headers`).append(`<th>${d}</th>`));

const indexRange = data.reduce((acc, { device }, index) =>
  ({ ...acc, [device]: {
    first: acc[device]?.first ?? index,
    last: index || acc[device]?.last
  } }), {});

console.log(indexRange);

data.forEach((record, rowIndex) => {
  $(`#body_deets`).append(`<tr></tr>`);
  const { device } = record;
  const { first, last } = indexRange[device];
  fields.forEach((field, colIndex) => {
    const value = record[field];
    if (colIndex === 0) {
      if (rowIndex === first) {
        const rowSpan = last - first + 1;
        $(`#body_deets > tr:last`).append(`<td rowspan="${rowSpan}">${value}</td>`);
      } 
    } else {
      $(`#body_deets > tr:last`).append(`<td>${value}</td>`);
    }
  });
});
table {
  border-collapse: collapse;
}

table, th, td {
  border: thin solid #CCC;
}

th, td {
  padding: 0.33em;
}

thead > tr {
  background: #DDD;
}

tbody tr:nth-child(even) {
  background: #EEE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table class="table">
  <thead>
    <tr id="headers"></tr>
  </thead>
  <tbody id="body_deets"></tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.