0

im relatively new to web development and im encountering an issue with my js code. ive implemented a filter functionality using js in my website but it seems to have interfered with the collapse feature to and made it stop working properly. but the collapse functionality works again when clearing the filters ive looked into the site who could have the same problem as me but i cant seem to make them work on my code

heres my setup:

  • i have a table where each row can be collapsed to view additional information
  • ive added js filtering to filter the rows based on certain colums
  • the filter works fine but when a filter is active i cant open the collapsed rows to view the details
  • i have my app.blade.php in layouts directory and i store the scripts and styles there that i generally use

Heres my code:

@extends('layouts.app')

@section('content')
    <div class="container">

        <button class="btn btn-success mb-3" id="toggleFilterForm">
            <i class="fas fa-filter"></i> Hide Filter
        </button> 

        <div id="filterForm">
            <div class="row mb-3">
                <div class="col">
                    <input type="text" id="col1" class="form-control" placeholder="Engineer Code">
                </div>
                <div class="col">
                    <input type="text" id="col2" class="form-control" placeholder="Live">
                </div>
                <div class="col">
                    <input type="text" id="col3" class="form-control" placeholder="Status">
                </div>
                <div class="col">
                    <input type="date" id="col4" class="form-control">
                </div>
                <div class="col">
                    <button id="applyFilters" class="btn btn-primary">
                        <i class="fas fa-search"></i> Filter
                    </button>
                </div>
                <div class="col">
                    <button id="clearFilters" class="btn btn-secondary">
                        <i class="fas fa-times-circle"></i> Clear Filters
                    </button>
                </div>
            </div>
        </div>

        <div class="table-responsive">
            <table class="table table-striped" id="dataTable">
                <thead>
                    <tr>
                        <th>Col 1</th>
                        <th>Col 2</th>
                        <th>Col 3</th>
                        <th>Col 4</th>
                        <th>Date Time</th>
                    </tr>
                </thead>
                <tbody id="tableBody">
                @foreach($fileData as $fileIndex => $file)
                    <tr data-bs-toggle="collapse" data-bs-target="#collapse{{ $fileIndex }}" aria-expanded="false" aria-controls="collapse{{ $fileIndex }}">
                        <td>{{ $file['content']['col1'] }}</td>
                        <td>{{ $file['content']['col2'] }}</td>
                        <td>{{ $file['content']['col3'] }}</td>
                        <td>{{ $file['content']['col4']) }}</td>
                        <td>{{ date('Y-m-d H:i:s', $file['content']['col5']) }}</td>
                    </tr>
                    @if (!empty($file['content']['data']))
                    <tr>
                        <td colspan="5" class="p-0">
                            <div class="collapse" id="collapse{{ $fileIndex }}">
                                <div class="card card-body">
                                    <table class="table table-bordered">
                                        <thead>
                                            <tr>
                                                <th>
                                                    <button class="btn btn-danger" onclick="toggleCollapse('collapse{{ $fileIndex }}')"><i class="fas fa-times"></i> Close</button>
                                                </th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                                <tr>
                                                    <td data-bs-toggle="collapse" data-bs-target="#collapse{{ $fileIndex }}-{{ $subKeyIndex }}" aria-expanded="false" aria-controls="collapse{{ $fileIndex }}-{{ $subKeyIndex }}">{{ $subKeyIndex }}</td>
                                                    <td colspan="5">{{ count($subKey) }} Record(s)</td>
                                                </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </td>
                    </tr>
                    @endif
                @endforeach
                </tbody>
            </table>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {

            document.getElementById('applyFilters').addEventListener('click', function() {
                const col1 = document.getElementById('col1').value.toLowerCase();
                const col2 = document.getElementById('col2').value.toLowerCase();
                const col3 = document.getElementById('col3').value.toLowerCase();
                const col4 = document.getElementById('col4').value;

                const topLevelRows = document.querySelectorAll('#tableBody > tr');

                topLevelRows.forEach(row => {
                    const cols = row.getElementsByTagName('td');

                    const col1Text = cols[0] ? cols[0].innerText.toLowerCase() : '';
                    const col2Text = cols[1] ? cols[1].innerText.toLowerCase() : '';
                    const col3Text = cols[2] ? cols[2].innerText.toLowerCase() : '';
                    const col4Text = cols[4] ? cols[4].innerText.split(' ')[0] : '';

                    let match = true;
                    if (col1 && !col1Text.includes(col1)) match = false;
                    if (col2 && !col2Text.includes(col2)) match = false;
                    if (col3 && !col3Text.includes(col3)) match = false;
                    if (col4 && col4Text !== col4) match = false;

                    if (match) {
                        row.style.display = '';
                    } else {
                        row.style.display = 'none';
                    }
                });
            });

            document.getElementById('clearFilters').addEventListener('click', function() {
                document.getElementById('col1').value = '';
                document.getElementById('col2').value = '';
                document.getElementById('col3').value = '';
                document.getElementById('col4').value = '';

                const rows = document.querySelectorAll('#tableBody > tr');
                rows.forEach(row => row.style.display = '');

            });

            document.getElementById('toggleFilterForm').addEventListener('click', function() {
                const filterForm = document.getElementById('filterForm');
                if (filterForm.style.display === 'none') {
                    filterForm.style.display = 'block';
                    this.innerHTML = '<i class="fas fa-filter"></i> Hide Filter';
                } else {
                    filterForm.style.display = 'none';
                    this.innerHTML = '<i class="fas fa-filter"></i> Show Filter';
                }
            });
    </script>

@endsection

I expect to be able to open rows to view their info while a filter is active but it doesnt work

1 Answer 1

0

Your filtering is setting row.style.display = 'none'; for all rows that don't match the filter criteria. This includes all the $file['content']['data'] rows, so toggling the collapse status of the inner div does nothing.

You could add a specific class to the main rows and use that in your topLevelRows selection.

<tr class="filterable" data-bs-toggle="collapse" data-bs-target="#collapse{{ $fileIndex }}" aria-expanded="false" aria-controls="collapse{{ $fileIndex }}">
const topLevelRows = document.querySelectorAll('#tableBody > tr.filterable');

And then to make sure the related collapsible elements are not shown:

row.style.display = 'none';
document.querySelectorAll(row.dataset.bsTarget).forEach(t => t.classList.remove('show'));

Or, if you want to maintain the show/hide status of any filtered out rows you could:

if (match) {
    row.style.display = '';
    document.querySelectorAll(row.dataset.bsTarget).forEach(t => t.parentElement.parentElement.style.display = '');
} else {
    row.style.display = 'none';
    document.querySelectorAll(row.dataset.bsTarget).forEach(t => t.parentElement.parentElement.style.display = 'none');
}
1
  • 1
    oh so all my other rows are getting filtered by the when i get them using const topLevelRows = document.querySelectorAll('#tableBody > tr'); that was why when i open anything when im filtering the table then remove the filter, it will get opened ill have to be careful next time. thank you this worked!
    – Sotg
    Commented May 22 at 1:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.