Adding Filters to a Dynamically Generated Html Table

Adding Filters to a Dynamically Generated Html Table

I'm currently trying to add column-level filtering to an HTML table, generated from a click event listener, using the TableFilter JavaScript library, however I'm receiving the following error in the console:

Error: Could not instantiate TableFilter: HTML table requires at least 1 row.

The code I'm using to generate the table is below; in essence I'm taking in an array of objects, then looping through them to create a header row, then data rows and then appending the table to a <div>. The table itself renders without issue, but I'm unable to attach filters - could anyone shed any light on why this error is occurring? I'd suspected it might be something to do with trying to add a filter to the table before the element had been rendered, but I couldn't see why that would be the case. I'm aware that the documentation for the library recommends adding a <script> tag under the table, and I've also tried this however I'm not sure how to do that correctly since the table doesn't exist until the click event takes place (hence adding it to the onclick function).

HTML

<html>
    <head>
        <script src="script.js"></script>
        <script src="/TableFilter/dist/tablefilter/tablefilter.js"></script>
    </head>
    <body>
        <button id="my-button">Create Table</button>
        <div id="my-table-container">
            <!-- table -->
        </div>
        <script>
            button = document.getElementById('my-button');
            button.addEventListener('click', renderTable);
        </script>
    </body>
</html>

JavaScript

const createTableFromObjectArray = (data, containerRef, tableRef) => {
    // elements
    let container = document.getElementById(containerRef);
    let table = document.createElement('table');
    table.setAttribute('id', tableRef);
    
    // clear the DOM if the table is already present
    while (container.firstChild) {
        container.removeChild(container.firstChild);
    }

    // create header
    let headerRow = document.createElement('tr');
    const colNames = Object.keys(data[0]);
    colNames.forEach(name => {
        let headerCell = document.createElement('th');
        let headerText = document.createTextNode(name);
        headerCell.appendChild(headerText);
        headerRow.append(headerCell);
    });
    table.appendChild(headerRow);

    // add rows to table
    data.forEach(doc => {
        let tableRow = document.createElement('tr');
        Object.values(doc).forEach(value => {
            let rowCell = document.createElement('td');
            let cellText = document.createTextNode(value);
            rowCell.appendChild(cellText);
            tableRow.appendChild(rowCell);
        });
        table.appendChild(tableRow);
    });

    // add table to DOM and add filters
    container.appendChild(table);
    let tf = new TableFilter(table, {
        base_path: '/TableFilter/dist/tablefilter/'
    });
    tf.init();
}

const renderTable = () => {
    const data = [{'Name': 'John', 'Eyes': 'Blue', 'Hair': 'Brown'}];
    const containerRef = 'my-table-container';
    const tableRef = 'my-table';
    createTableFromObjectArray(data, containerRef, tableRef);
}
4
James H. Sterling
Author

James H. Sterling

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.