Search code examples
javascriptarraysdatatablearrow-functions

Create html table based on two object arrays: one containing the data, and the other including the columns (including the data array attribute names)


I'm rendering a table based on an objects array, for searching,

 /*
    ============================================================================================================
    ============================================================================================================
  
    Purpose: create html table based on two JSON arrays: array with data, and array with columns to be rendered
  
    ============================================================================================================
    ============================================================================================================
    */

    /* Store the array with the data to be filtered in a constant */
    const dataArray =
      [
        {
          "Category": "Storage & Organization",
          "ID": 1,
          "Product": "Eldon Base for stackable storage shelf, platinum",

        },
        {
          "Category": "Appliances",
          "ID": 2,
          "Product": "1.7 Cubic Foot Compact \"Cube\" Office Refrigerators"
        },
        {
          "Category": "Binders and Binder Accessories",
          "ID": 3,
          "Product": "Cardinal Slant-D-Ring Binder, Heavy Gauge Vinyl"
        }
      ]

    /* Store the "columns" array in a constant
    This constant includes the data attrubute names for the columns that will be displayed */
    const columnsArray =
      [
        {
          "attributeName": "Category"
        },
        {
          "attributeName": "Product"
        },
        {
          "attributeName": "ID"
        }
      ];

    // Function to display array objects as html table
    const displayAsTableRows = (dataArray) => {
      /* Create an table row for each array object */
      const htmlString = dataArray.map((object) => {
        return `
            <tr>
                <td>${object.ID}</td>
                <td>${object.Category}</td>
                <td>${object.Product}</td>
            </tr>
        ` ;
      }).join('');
      // Render table in "dataTable" html table element
      document.getElementById('dataTable').innerHTML = htmlString;
    };

    // Display objects array as html table when loading the page for the first time
    displayAsTableRows(dataArray);
  <table id="dataTable"></table>

I can get the columns array attribute names just by doing: columnsArray.map ( column=> column.attributeName ) to get an array with the attribute names: ["Category", "Product", "ID"]

However, I'm not sure how to "merge" the columnsArray inside the "dataArray" map, so the html table renders dynamically with the number of columns and content depending on the "columnsArray" elements content.

Basically, I'm hoping to avoid having to hardcode this:

                <td>${object.ID}</td>
                <td>${object.Category}</td>
                <td>${object.Product}</td>

And having instead something like this: (it obviously doesn't work ...)

// Function to display array objects as html table
    const displayAsTableRows = (dataArray) => {
      /* Create an table row for each array object */
      const htmlString = dataArray.map((object) => {
        return `
            <tr>
                <td>${object.<<get the content for each "columnsArray" element "attributeName" content >>}</td>
            </tr>
        ` ;
      }).join('') ;
      // Render table in "dataTable" html table element
      document.getElementById('dataTable').innerHTML = htmlString ;
    };

Any help would be very much appreciated!! :)


Solution

  • Here is a tested version

    Only column keys hardcoded

    const dataArray = [{
        "Category": "Storage & Organization",
        "ID": 1,
        "Product": "Eldon Base for stackable storage shelf, platinum",
    
      },
      {
        "Category": "Appliances",
        "ID": 2,
        "Product": "1.7 Cubic Foot Compact \"Cube\" Office Refrigerators"
      },
      {
        "Category": "Binders and Binder Accessories",
        "ID": 3,
        "Product": "Cardinal Slant-D-Ring Binder, Heavy Gauge Vinyl"
      }
    ]
    
    const columnsArray = [{
      "attributeName": "Category",
      "isSearchable": true,
      "headerName": "Type"
    }, {
      "attributeName": "Product",
      "isSearchable": true,
      "headerName": "Product name"
    }]
    
    const columnNames = columnsArray.map(column => column.attributeName)
    
    const thead = `<tr>${columnsArray.map(({headerName}) => `<th>${headerName}</th>`).join("")}</tr>`;
    
    const tbody = dataArray.map(object => `<tr>
      ${columnNames.map(columnName => `<td>${object[columnName]}</td>`).join("")}
    </tr>`).join("");
    
    document.getElementById("th").innerHTML = thead;
    document.getElementById("tb").innerHTML = tbody;
    <table>
      <thead id="th"></thead>
      <tbody id="tb"></tbody>
    </table>