【问题标题】:How to programmatically create an irregular table by JavaScript/jQuery?如何通过 JavaScript/jQuery 以编程方式创建不规则表格?
【发布时间】:2020-07-23 09:30:35
【问题描述】:

有一个excel,它的一些行被合并了,我们需要创建一个与它在excel中显示的布局相同的表,并从数据库中填充数据。

布局如下:

Excel Table

我尝试了以下代码:

for (let group of group_list) {
      var table = document.createElement("table")
      table.setAttribute("id","summaryTbl");
      $('#main').append(table);
      var row = table.insertRow(0);
      row.insertCell(0).outerHTML = "<th>Column 1</th>";
      row.insertCell(1).outerHTML = "<th>Column 2</th>";
      row.insertCell(2).outerHTML = "<th>Column 3</th>";
      row.insertCell(3).outerHTML = "<th>Column 4</th>";
      $('#main').append('</thead>');

但不知何故,它总是显示“tbody”而不是“thead”:

Console log

以下代码除外:

var table = document.createElement("table")
table.setAttribute("id","summaryTbl");
var row = table.insertRow(0);
row.insertCell(0).outerHTML = "<th>Column 1</th>";
        ...
$('#summaryTbl tr:last').after('<tr><td>'+"Test 1"+'</td>');
        ...
$('#summaryTbl').append('<tr><td>'+ "Test 2"+'</td>');

有没有更好的方法来生成这样一个不规则的表格?使用一些 JavaScript 库还是仅仅通过 for-loop 和 if-else 条件?

【问题讨论】:

  • 您需要在所需单元格上使用rowspan 属性。不需要库来执行此操作,它是纯 HTML。

标签: javascript jquery dom


【解决方案1】:

我看过您的帖子并尝试将其作为自己的练习,我不妨分享一下结果。 这不完全相同,因为在您的图片中,“1.1.1.1.x”填充到左侧,“2.3.x.1”比其他行小,我没有做这些棘手的案例。

const values = ["1.1.1.1.1", "1.1.1.1.2", "1.1.1.1.3", "1.1.1.1.4", "1.1.1.1.5", "1.2.1.1.1", "2.1.1.1.1", "2.2.1.1.1", "2.2.2.1.1", "2.2.3.1.1", "2.3.1.1", "2.3.2.1", "2.3.3.1", "2.3.4.1"]

// create a nested object from values
// 1.2.3 becomes {1:{2:{3:}}}
const transformedValues = (() => {
  const output = {}
  values.forEach(el => {
    let tmp = output
    el.split(".").forEach(val => {
      if (!tmp[val]) {
        tmp[val] = {}
      }
      tmp = tmp[val]
    })
  })
  return output
})()
// find the object max depth, for the column count
const maxDepth = (function rec(obj, depth = 0){
  return Math.max(depth, ...Object.values(obj).map(val => rec(val, depth + 1)))
})(transformedValues)

// header name generator (more than 26 and you'll go into non alphanumeric)
let headerASCII = "A".charCodeAt(0)
const getNextHeader = () => String.fromCharCode(headerASCII++)

// create the table
const table = document.createElement("table")

/*
@param {string} val the text of the created cell
@param {Object} next the childs of the object
@param {HTMLRowElement | null} row the last created
@param {boolean} newRow if we need to create a new row
@param {boolean} newHeader if we need to create a new thead
*/
function createTable(val, next, row, newRow = false, newHeader = false) {
  // create new header
  if (newHeader) {
    const head = document.createElement("thead")
    // with depth - 1 cells (first one takes 2 columns)
    for (let i = 0; i < maxDepth - 1; i++) {
      let th  = document.createElement("th")
      th.textContent = getNextHeader()
      if(i === 0) {th.colSpan = 2}
      head.appendChild(th)
    }
    table.appendChild(head)
  }
  // create new row
  if (newRow) {
    row = document.createElement("tr")
    table.appendChild(row)
  }
  // new cell
  const cell = document.createElement("td")
  cell.textContent = val
  // span on enought rows to align with every child
  cell.rowSpan = (function childCount(obj) {return Object.values(obj).reduce((acc, el) => acc + childCount(el), 0) || 1})(next)
  row.appendChild(cell)
  
  // recurcive call
  Object.entries(next).forEach(([key, value], i) => {
    createTable(`${val}.${key}`, value, row, i !== 0)
  })
}
// first call
Object.entries(transformedValues).forEach(([key, value]) => {
  createTable(key, value, null, true, true)
})

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

table th, table td {
  border: 2px solid black;
}

table th {
  background-color: cyan;
}

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 1970-01-01
    • 2011-06-16
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    相关资源
    最近更新 更多