javascripthtmlcssbootstrap-5

How to use sort, search and show per page in Bootstrap 5 table


I have a very simple table:

enter image description here

And I include Bootstrap 5:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>

I want to understand how can I implement searching by values (looking for a value in specific columns), choosing the number of rows that are currently shown and sorting by columns

I know that in the past this could be done with $('#Table').bootstrapTable, but I did not find examples of how to do this in version 5


Solution

  • I realized that ready-made solutions require a cascade of imports (including jquery). It's much easier to write your own code, which is what I did

    Here is a basic example. I've stripped out all class attributes for simplicity. I also added a value for the <td> tags, but you don't have to if you don't have a complex nested structure (i.e. just a <td>value</td>)

    <form>
        <input placeholder="Search" id="search-in-table" onkeypress="return event.keyCode != 13;">
    </form>
    
    <p>Show per page:</p>
    <select id="form-select-coins">
        <option value="10" selected>10</option>
        <option value="20">20</option>
        <option value="30">30</option>
    </select>
    
    <table id="coins-table">
    
        <thead>
    
            <tr>
                <th>Name</th>
                <th>Holdings</th>
                <th>Price</th>
                <th>Avg. Buy Price</th>
                <th>Wallet Balance</th>
                <th>Profit/Loss</th>
            </tr>
    
        </thead>
    
        <tbody>
    
            <tr coin="COIN">
                <td value="COIN">COIN</td>
                <td value="TOTAL_COINS">TOTAL_COINS</td>
                <td value="CURRENT_PRICE">CURRENT_PRICE</td>
                <td value="AVG_BUY_PRICE">AVG_BUY_PRICE</td>
                <td value="WALLET_BALANCE">WALLET_BALANCE</td>
                <td value="PROFIT_LOSS">PROFIT_LOSS</td>
            </tr>
    
        </tbody>
    
    </table>
    
    function hide_table_elements(table_id, visible) {
        // Shows only the first `visible` table elements
        table_elements = document.getElementById(table_id).children[1].children
    
        for (const element of table_elements) {
            if (visible == 0) {
                element.style.display = 'none'
            }
            else {
                element.style.display = 'table-row'
                visible -= 1
            }
        }
    }
    
    // Use below solution for <td> without `value` attribute
    // const getCellValue = (tr, idx) => tr.children[idx].innerText.replace('$', '') || tr.children[idx].textContent.replace('$', '');
    const getCellValue = (tr, idx) => tr.children[idx].getAttribute('value')
    
    const comparer = (idx, asc) => (a, b) =>
        ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2))
        (getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx))
    
    const reload_table = () => hide_table_elements('coins-table', document.getElementById('form-select-coins').value)
    
    window.addEventListener('load', function () {   
        reload_table()
    
        // Show per page
        document.getElementById('form-select-coins').addEventListener('change', function() {
            counter = this.value
            hide_table_elements('coins-table', this.value)
        });
    
        // Search in table
        document.getElementById('search-in-table').addEventListener('input', function() {   
            rows = document.getElementById('coins-table').children[1].querySelectorAll('tr:nth-child(n)')
            value = this.value.toLowerCase()
    
            if (value == '')
                return reload_table()
    
            for (const row of rows) {
                if (row.getAttribute('coin').toLowerCase().includes(value)) {
                    row.style.display = 'table-row'
                } else {
                    row.style.display = 'none'
                }
            }       
        });
    
        // Sort table
        document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
            const table = document.getElementById('coins-table').children[1]
    
            Array.from(table.querySelectorAll('tr:nth-child(n)'))
                .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
                .forEach(tr => table.appendChild(tr));
            
            reload_table()
        })));
    });
    

    It's cheap and fast, but if you want to use ready-made solutions, look here