使用JSON和JQuery合并和分组表

时间:2019-03-27 07:54:03

标签: javascript jquery html json

将行跨度分配给表并根据父行将它们分组时,我遇到了问题。我已经尝试找到一些解决方案,但是大多数解决方案是合并相同的值而不是将它们分组。

  var data = 
  [
    {
      "LEVEL_1": "LEVEL 1",
      "LEVEL_2": "LEVEL 1.1",
      "LEVEL_3": "LEVEL 1.1.1",
    },
    {
      "LEVEL_1": "LEVEL 1",
      "LEVEL_2": "LEVEL 1.2",
      "LEVEL_3": "LEVEL 1.2.1",
    },
     {
      "LEVEL_1": "LEVEL 1",
      "LEVEL_2": "LEVEL 1.2",
      "LEVEL_3": "LEVEL 1.2.2",
    },
    {
      "LEVEL_1": "LEVEL 2",
      "LEVEL_2": "LEVEL 2.1",
      "LEVEL_3": "LEVEL 2.1.1",
    },
    {
      "LEVEL_1": "LEVEL 2",
      "LEVEL_2": "LEVEL 2.1",
      "LEVEL_3": "LEVEL 2.1.2",
    },
    {
      "LEVEL_1": "LEVEL 2",
      "LEVEL_2": "LEVEL 2.2",
      "LEVEL_3": "LEVEL 2.2.1",
    },
    {
      "LEVEL_1": "LEVEL 2",
      "LEVEL_2": "LEVEL 2.2",
      "LEVEL_3": "LEVEL 2.2.2",
    }
  ];

  var tableStr = '';
  $.each(data, function(index, value) { 
    tableStr += '<tr>' + 
       '<td>'+value.LEVEL_1+'</td>'+
       '<td>'+value.LEVEL_2+'</td>'+
       '<td>'+value.LEVEL_3+'</td>'+
     '</tr>';
  }); 
  $('#user tbody').html(tableStr);
 table { 
      border-collapse: collapse;
    }

    td {
      padding: 20px; 
      border: 1px solid black; 
      text-align: center;
    }

    th {
      padding: 20px; 
      border: 1px solid black; 
      text-align: center;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="user">
    <thead>
        <tr>
          <th>LEVEL 1</th>
          <th>LEVEL 2</th>
          <th>LEVEL 3</th>
        </tr>
        <tr>
        </tr>
    </thead>
    <tbody> 
    </tbody>
</table>

我期望的结果:
enter image description here


我总是发现一个结果,它从一开始就起作用。但是当我添加另一个级别但相同的数据时,它总是像这样
enter image description here
从Ajax请求提供的JSON数据已经这样给出了。我是否需要修改JSON数据并将其分组?或者可以使用给定的JSON数据完成此操作?如何使用Jquery和JSON数据完成此操作?预先感谢

3 个答案:

答案 0 :(得分:1)

借助此question,我设法合并了第一级。

var data = [{
    "LEVEL_1": "LEVEL 1",
    "LEVEL_2": "LEVEL 1.1",
    "LEVEL_3": "LEVEL 1.1.1",
  },
  {
    "LEVEL_1": "LEVEL 1",
    "LEVEL_2": "LEVEL 1.2",
    "LEVEL_3": "LEVEL 1.2.1",
  },
  {
    "LEVEL_1": "LEVEL 1",
    "LEVEL_2": "LEVEL 1.2",
    "LEVEL_3": "LEVEL 1.2.2",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.1",
    "LEVEL_3": "LEVEL 2.1.1",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.1",
    "LEVEL_3": "LEVEL 2.1.2",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.2",
    "LEVEL_3": "LEVEL 2.2.1",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.2",
    "LEVEL_3": "LEVEL 2.2.2",
  }
];

for (i = 0; i < data.length; i++) {
  var l1 = data[i].LEVEL_1;
  data[i].rowspan = 1;
  for (j = i + 1; j < data.length; j++) {
    var l2 = data[j].LEVEL_1;
    if (l1 == l2) {
      data[i].rowspan += 1;
    } else {
      break;
    }
  }
  i = j - 1;
}
var tableStr = '';
$.each(data, function(index, value) {
  if (value.rowspan > 1) {
    tableStr += '<tr>' +
      '<td rowspan="' + value.rowspan + '">' + value.LEVEL_1 + '</td>' +
      '<td>' + value.LEVEL_2 + '</td>' +
      '<td>' + value.LEVEL_3 + '</td>' +
      '</tr>';
  } else {
    tableStr += '<tr>' +
      '<td>' + value.LEVEL_2 + '</td>' +
      '<td>' + value.LEVEL_3 + '</td>' +
      '</tr>';
  }


});
$('#user tbody').html(tableStr);
table {
  border-collapse: collapse;
}

td {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}

th {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="user">
  <thead>
    <tr>
      <th>LEVEL 1</th>
      <th>LEVEL 2</th>
      <th>LEVEL 3</th>
    </tr>
    <tr>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>

答案 1 :(得分:0)

我为您提供解决方案。它可能不是最优雅的,但可以使用

首先,我将数据从JSON转换为一个嵌套对象,该对象计算较低级别项的出现。

第二步是遍历该嵌套对象并相应地创建表,tr和td,并将​​步骤1中的计数值用作rowspan属性值。

我什至不需要jQuery,只需要VanillaJS。

console.clear();

var data = [
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.1",
    LEVEL_3: "LEVEL 1.1.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.1"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.1"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.2"
  }
];

const transformData = (data) => {
  let t = {};

  data.forEach((item, index, source) => {
    let l1 = item.LEVEL_1,
        l2 = item.LEVEL_2,
        l3 = item.LEVEL_3;
    t[l1]                         = t[l1]                         || {text: l1, content: {}, count: 0};
    t[l1].content[l2]             = t[l1].content[l2]             || {text: l2, content: {}, count: 0};
    t[l1].content[l2].content[l3] = t[l1].content[l2].content[l3] || {text: l3, content: {}, count: 0};
    t[l1].count++
    t[l1].content[l2].count++
    t[l1].content[l2].content[l3].count++
  })
  return t;
}

const transformDataTable = (tdata) => {

  const table = document.createElement('table');

  for (l1 in tdata) {
    const td1 = document.createElement('th')
    td1.textContent = tdata[l1].text;
    td1.setAttribute('rowspan', tdata[l1].count)
    let done1 = false;

    for (l2 in tdata[l1].content) {
      const td2 = document.createElement('td')
      td2.textContent = tdata[l1].content[l2].text;
      td2.setAttribute('rowspan', tdata[l1].content[l2].count)
      let done2 = false;
      
      for (l3 in tdata[l1].content[l2].content) {
        const td3 = document.createElement('td')
        td3.textContent = tdata[l1].content[l2].content[l3].text;
        td3.setAttribute('rowspan', tdata[l1].content[l2].content[l3].count)
        const tr = document.createElement('tr')
        !done1 && tr.appendChild(td1) && (done1 = true);
        !done2 && tr.appendChild(td2) && (done2 = true);
        tr.appendChild(td3);
        table.appendChild(tr);
      }
    }
  }
  return table;
}


const tdata = transformData(data);
const table = transformDataTable(tdata);


document.body.appendChild(table)
table {
  border-collapse: collapse;
}

td,
th {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}

通过一些修改,您可以自己对每个列进行排序

console.clear();

var data = [
  {
    LEVEL_1: "LEVEL 3",
    LEVEL_2: "LEVEL 3.1",
    LEVEL_3: "LEVEL 3.1.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.1",
    LEVEL_3: "LEVEL 1.1.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.1"
  },
  {
    LEVEL_1: "LEVEL 3",
    LEVEL_2: "LEVEL 3.1",
    LEVEL_3: "LEVEL 3.1.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.1"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.3"
  }
  
];

const transformData = (data) => {
  let t = {};

  data.forEach((item, index, source) => {
    let l1 = item.LEVEL_1,
        l2 = item.LEVEL_2,
        l3 = item.LEVEL_3;
    t[l1]                         = t[l1]                         || {text: l1, content: {}, count: 0};
    t[l1].content[l2]             = t[l1].content[l2]             || {text: l2, content: {}, count: 0};
    t[l1].content[l2].content[l3] = t[l1].content[l2].content[l3] || {text: l3, content: {}, count: 0};
    t[l1].count++
    t[l1].content[l2].count++
    t[l1].content[l2].content[l3].count++
  })
  return t;
}

const transformDataTable = (tdata, sort = (a,b) => b-a, sort1 = sort, sort2 = sort1) => {

  const table = document.createElement('table');

  for (l1 of Object.keys(tdata).sort(sort)) {
    const td1 = document.createElement('th')
    td1.textContent = tdata[l1].text;
    td1.setAttribute('rowspan', tdata[l1].count)
    let done1 = false;

    for (l2 of Object.keys(tdata[l1].content).sort(sort1)) {
      const td2 = document.createElement('td')
      td2.textContent = tdata[l1].content[l2].text;
      td2.setAttribute('rowspan', tdata[l1].content[l2].count)
      let done2 = false;
      
      for (l3 of Object.keys(tdata[l1].content[l2].content).sort(sort2)) {
        const td3 = document.createElement('td')
        td3.textContent = tdata[l1].content[l2].content[l3].text;
        td3.setAttribute('rowspan', tdata[l1].content[l2].content[l3].count)
        const tr = document.createElement('tr')
        !done1 && tr.appendChild(td1) && (done1 = true);
        !done2 && tr.appendChild(td2) && (done2 = true);
        tr.appendChild(td3);
        table.appendChild(tr);
      }
    }
  }
  return table;
}

const asc = (a,b) => b-a
const desc = (a,b) => a-b

const tdata = transformData(data);
const table = transformDataTable(tdata, desc, asc);


document.body.appendChild(table)
table {
  border-collapse: collapse;
}

td,
th {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}

答案 2 :(得分:0)

我将其分为两个步骤:1.从输入数据生成树状结构以允许行跨计数; 2.绘制表的行和列。

整个代码尽可能通用,以避免硬编码的列数。

我还添加了一个动态表头。如果在数据结构中添加另一列,则HTML表标题也会被更新。例如,可以使用相同的代码添加第四级,例如"LEVEL_4": "LEVEL 1.2.2.1"到一行或多行。

var data = [
    {
        "LEVEL_1": "LEVEL 1",
        "LEVEL_2": "LEVEL 1.1",
        "LEVEL_3": "LEVEL 1.1.1"
    },
    {
        "LEVEL_1": "LEVEL 1",
        "LEVEL_2": "LEVEL 1.2",
        "LEVEL_3": "LEVEL 1.2.1"
    },
    {
        "LEVEL_1": "LEVEL 1",
        "LEVEL_2": "LEVEL 1.2",
        "LEVEL_3": "LEVEL 1.2.2"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.1",
        "LEVEL_3": "LEVEL 2.1.1"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.1",
        "LEVEL_3": "LEVEL 2.1.2"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.2",
        "LEVEL_3": "LEVEL 2.2.1"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.2",
        "LEVEL_3": "LEVEL 2.2.2"
    }
];

/**
 * Generate rows and columns for the table using the JSON data.
 *
 * @param {Object} data
 * @param {HTMLTableSectionElement} tableBody
 * @param {HTMLTableSectionElement} tableHead
 */
function setTableContent(data, tableBody, tableHead) {
    /* The rowspan is stored here depending on the label of each column */
    var columnRowspans = {};

    var columnHeadings = {};

    /**
     * Translate the data into a tree-like structure
     *
     * @param {JSON} data
     * @return {Array}
     */
    function translateData(data) {
        var rows = [];
        /* Iterate over each row in the dataset */
        data.forEach(function (row) {
            var columns = [],
                label;
            /* Find the individual columns */
            for (var key in row) {
                /* Store the columns header */
                columnHeadings[key] = true;

                label = row[key];
                /* Skip those columns that were already added */
                if (columnRowspans[label]) {
                    columnRowspans[label]++;
                    continue;
                }
                columns.push(label);
                columnRowspans[label] = 1;
            }
            rows.push(columns);
        });
        return rows;
    }

    /* Template string used for a single field in the table */
    var cellTemplate = '<td rowspan="{rowspan}">{content}</td>';

    /* Output */
    var html = '';
    translateData(data).forEach(function (row, index) {
        html += '<tr>';
        row.forEach(function (columnLabel) {
            /* Use the stored rowspans here to generate columns */
            html += cellTemplate
                .replace('{rowspan}', columnRowspans[columnLabel])
                .replace('{content}', columnLabel);
        });
        html += '</tr>';
    });

    if (tableBody instanceof HTMLTableSectionElement) {
        tableBody.innerHTML = html;
    }

    if (tableHead instanceof HTMLTableSectionElement) {
        var thead = '<tr>';
        Object.keys(columnHeadings).forEach(function (heading) {
            thead += '<th>' + heading.replace('_', ' ') + '</th>';
        });
        thead += '</tr>';
        tableHead.innerHTML = thead;
    }
}

setTableContent(data, document.querySelector('#user tbody'), document.querySelector('#user thead'));
 table { 
      border-collapse: collapse;
    }

    td {
      padding: 20px; 
      border: 1px solid black; 
      text-align: center;
    }

    th {
      padding: 20px; 
      border: 1px solid black; 
      text-align: center;
    }
<table id="user">
    <thead>
    </thead>
    <tbody> 
    </tbody>
</table>