简体   繁体   中英

Drawing HTML table with dynamic columns/rows

I have an array of objects like this:

const reports = [
      {
        user: "John",
        document: [
          {            
            document_name: "word",
            document_type: 1,
            cid: 2,
          },
          {           
            document_name: "excel",
            document_type: 1,
            cid: 2,
          },
        ],
      },
      {
        user: "Matt",
        document: [
          {            
            document_name: "access",
            document_type: 1,
            cid: 1,
          },
          {            
            document_name: "word",
            document_type: 1,
            cid: 3,
          },
        ],
      },
    ];

Is there a way to draw a HTML table where columns would be the users, and rows would be document_names (in both cases without duplicates). So, someting like this.

John Matt
word 2 1
excel 2
access 1

Cells with numeric values are populated with corresponding cid values.

Any help, even regarding const reports refactor, is appreciated.

Tables are created row-wise, not column wise. That is to say in HTML the row tr is the wrapper for several columns. This is important for your problem, since your structure is organised column-wise (user first, not document first).

At the same time, the number of columns is dynamic (determined by your data), and needs to be the same in all rows, even if a user is missing. The same counts for the rows. While the data can have gaps, the table cannot.

So by creating separate lists first, you can iterate easier on the two dimensions. In Database Theory this is called Normalization .

Part of normalization is to only store unique items, so you can use JavaScript Sets . When you add() an item, it's only added once, avoiding duplicates.

// this is pseudo-code to demonstrate the target structures
const users = Set(2) [ "John", "Matt" ];
const docs = Set(3) [ "word", "excel", … ]
const usages = [{user: "John", doc: "word", cid: 2}, …]

Then you can use for … in to iterate over your sets and create the columns and rows.

To make things easier, you can prepare the static structure of the table, and then use document.createElement() and .appendChild() to add the dynamic elements to the table.

You should create a table using<thead> and <th> elements to semantically associate the data. This will not only help users with disabilities navigate the table through assistive technology, it will also repeat the table head in printout.

 const reports = [{ user: "John", document: [{ document_name: "word", document_type: 1, cid: 2, }, { document_name: "excel", document_type: 1, cid: 2, }, ], }, { user: "Matt", document: [{ document_name: "access", document_type: 1, cid: 1, }, { document_name: "word", document_type: 1, cid: 3, }, ], }, ]; // Normalise data const users = new Set(reports.map(r => r.user)); const docs = new Set(); const usages = []; reports.forEach(r => r.document.forEach(d => { docs.add(d.document_name); usages.push({ user: r.user, doc: d.document_name, cid: d.cid }); })); // Add to the table // Create headers const theadTr = document.querySelector('thead tr'); for (const u of users) { const th = document.createElement('th'); th.innerHTML = u; theadTr.appendChild(th); } // Create data rows const tbody = document.querySelector('tbody'); for (const d of docs) { const tr = document.createElement('tr'); const th = document.createElement('th'); th.innerHTML = d; tr.appendChild(th); for (const u of users) { const td = document.createElement('td'); const ud = usages.find(ud => ud.user === u && ud.doc === d); if (ud) td.innerHTML = ud.cid; tr.appendChild(td); } tbody.appendChild(tr); }
 th, td { padding: .2em.5em; border: 1px solid gray; } thead tr { background-color: lightgray; color: black; } table { border-collapse: collapse; }
 <table> <caption>Document usage per user and document type</caption> <thead> <tr> <th></th> </tr> </thead> <tbody> </tbody> </table>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM