Best practice to filter data based on external radio buttons

Best practice to filter data based on external radio buttons

pharmoniepharmonie Posts: 8Questions: 1Answers: 0

Hi,

what is best practice to filter the data with radio buttons?

I am calling the datatable like:

var table = $('#tasks_table').DataTable({
            "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "method": "POST",
                "url": "<?=base_url();?>data_table",
                "data": function ( d ) {
                    d.business = "<?=$settings->business;?>";
                }
            }
        });

With the custom post data d.business I use a WHERE business = $business in MySQL.

The $settings->business; is the value I want to filter.

I have this form prior to my table:


<form id="filter_business"> <p> <span>Filter Business</span><br> <label> <input name="business" value="all" type="radio" <?=$settings->business=="all" ? 'checked' : '';?> /> <span>All&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </label> <label> <input name="business" value="systems_eu" type="radio" <?=$settings->business=="systems_eu" ? 'checked' : '';?> /> <span>Systems EU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </label> <label> <input name="business" value="systems_na" type="radio" <?=$settings->business=="systems_na" ? 'checked' : '';?> /> <span>Systems NA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </label> <label> <input name="business" value="fastener" type="radio" <?=$settings->business=="fastener" ? 'checked' : '';?> /> <span>Fastener&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </label> </p> </form>

I think about running a new query with new WHERE criteria and reload the table, but I think it makes more sence to load the enitre data and filter it later. And start with "all".

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    You are using server-side processing and passing the filter value to the server on each query, so all you need to do is call draw() whenever the radio button selection is changed.

    That said - you need to change d.business = "<?=$settings->business;?>"; to be dynamic. At the moment it is static - you need to evaluate it whenever that function is run:

    d.business = $(‘input[name=business]:checked’).val();
    

    should do it.

    Allan

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0

    Sound good, but my updated code doesn't redraw, when I switch the radios:

    <script>
        $(document).ready(function(){
    
            var table = $('#tasks_table').DataTable({
                "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
                "processing": true,
                "serverSide": true,
                "ajax": {
                    "method": "POST",
                    "url": "<?=base_url();?>data_table",
                    "data": function ( d ) {
                        d.business = $("input[name=business]:checked").val();
                    }
                }
            });
    
            $('#tasks_table').removeClass("dataTable");
            
            $('a.toggle-vis').on( 'click', function (e) {
                e.preventDefault();
                var column = table.column( $(this).attr('data-column') );
                column.visible( ! column.visible() );
            } );
    
            $('#filter_business input[type=radio]').change(function() {
                console.log("Test");
                table.draw();
            });
        });
    </script>
    

    I recognized two things: "Test" gets logged to the console and a "processing..." String appears in the middle of the table but stays and the table doesn't draw again.

    Overall I recognize, that when I generate my table from a php array with a foreach loop, my pagination is working. When I switch to server-side, It loads all rows without limit, but the pagination buttons are there and do not work.

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0

    Thinking about that... I'd prefer a solution that doesn't use server-side ajax and I'd like to switch back to php array.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Does your Test message print there? And does the data function inside the ajax object execute?

    I'd prefer a solution that doesn't use server-side ajax and I'd like to switch back to php array.

    I don't really know what you mean I'm afraid.

    Allan

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0

    Yes, they do.

    I mean, that I load the entire data from MySQL and buld the table like

    <tbody>
        <?php foreach($tasks as $task) : ?>
            <tr>
                <td><?=$task->name;?></td>
                <td><?=$task->business;?></td>
                 <!-- ... -->
            </tr>
        <?php endforeach;?>
    </tbody>
    

    And call it like

    <script>
        $(document).ready(function(){
    
            var table = $('#tasks_table').DataTable({
                "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
            });
    
            $('#filter_business input[type=radio]').change(function() {
                console.log("Test");
                table.draw();
            });
        });
    </script>
    

    The radio button form remains. How can I now redraw the datatable und filter on the business value?

  • kthorngrenkthorngren Posts: 20,143Questions: 26Answers: 4,736

    "Test" gets logged to the console and a "processing..." String appears in the middle of the table but stays and the table doesn't draw again.

    Your server script is not returning data or there is an error. Check your browser's console.

    I'd prefer a solution that doesn't use server-side ajax

    You might not need server side processing (which requires the server script to perform sorting, searching and paging) but can use ajax with client side processing. How many rows do you have? You can try removing serverSide: true then use search or column().search() instead of draw() to search the data client side.

    Kevin

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0
    edited July 2020

    The recommendation with column().search() works, but applies the filter to the search input field. Thus I can't perfom another search.
    Is it possible to hide the rows instead of searching, so that I'd use the search for other values on that filter?

  • kthorngrenkthorngren Posts: 20,143Questions: 26Answers: 4,736
    Answer ✓

    You can use a search plugin which will be independent of the search() and column().search() APIs. Here is an example:
    http://live.datatables.net/rosahuka/1/edit

    It uses draw() to have the plugin run when the checkbox is clicked.

    Kevin

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0

    That's exactly what I'm looking for! Thank you!

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0

    Just one question and then I'm fully fine: How can I modify the code so that I can have one checkbox filter for multiple values?
    In the given example, there will be one checkbox like

    <input type="checkbox" name="pos" value="Integration Specialist||Javascript Developer||System Architect">Important People
    
  • kthorngrenkthorngren Posts: 20,143Questions: 26Answers: 4,736

    You can use something like Javascript includes(). Convert the values into an array then use something like myArray.include(searchData[x] where x is the column. You just need to use the Javascript methods that meet your requirement.

    Kevin

  • pharmoniepharmonie Posts: 8Questions: 1Answers: 0
    edited August 2020

    Thank you. That's working. Just for reference, if someone runs into the same needs, here is the working code:

    $.fn.dataTable.ext.search.push(
        function( settings, searchData, index, rowData, counter ) {
            var positions = $('input:checkbox[name="project"]:checked').map(function() {
                return this.value;
            }).get();
    
            if (positions.length === 0) {
                return true;
            }
    
            if (positions.length > 0)
            {
                var values = positions[0].split('||');
                if (values.includes(searchData[8]))
                {
                    return true;
                }
            }
            
            return false;
        }
    );
    
This discussion has been closed.