skip to Main Content

I am working with Ajax and jQuery, I am working on sorting (without data tables), I am getting correct result but just want to display sorting icons (up, down), I want whenever I click on any column (name or symbol) for sort then "down" icon should display and after click on "down" icon should replace with "up" and whenever I click on another column both icons should remove and display on another
column for sort like previous. How can I do this ? I tried with following code but icons appending (showing multiple times), where I am wrong?

Here is my html:

<table border='1' width='100%' style='border-collapse: collapse;' id='postsList'>
    <thead>
        <tr>
            <th>S.no</th>
            <th class="column_sort" id="name" data-order="desc" href="#">Title</th>
            <th class="column_sort" id="symbol" data-order="desc" href="#">Symbol</th>
        </tr>
     </thead>
     <tbody></tbody>
</table>

And here is my script code:

$(document).ready(function(){  
    var timesClicked = 0;
    $(document).on('click', '.column_sort', function(event){
        event.preventDefault();
        var column_name = $(this).attr("id");  
        timesClicked++;
           
        if (timesClicked % 2 == 1) { // after first click(even clicks)
            $('#'+column_name+'').append('<img src="<?=base_url()?>/assets/img/DownArrow.png"/>');   
            $('#'+column_name+'').remove('<img src="<?=base_url()?>/assets/img/UpArrow.png"/>');
            var order = "ASC";
        }else{
            var order = "DESC";   // after second click(odd clicks)
            $('#'+column_name+'').remove('<img src="<?=base_url()?>/assets/img/DownArrow.png"/>');   
            $('#'+column_name+'').append('<img src="<?=base_url()?>/assets/img/UpArrow.png"/>');
        };

        var arrow = '';  
        var PageNumber= $("#pagination").find("strong").html();
        $(".column_sort").removeClass("active");
        $.ajax({  
            url:'<?=base_url()?>/Main/fetch_details/', 
            method:"POST",  
            data:{column_name:column_name, order:order ,PageNumber:PageNumber},  
            success:function(data) {  
                $("#postsList tr:not(:first)").remove();
                $("#postsList2").show();
                $('#'+column_name+'').addClass('active');
                return false;
            }
        }) 
    });  
});  

3

Answers


  1. How you display the arrow icons is up to you, for my example I simply used html entities. Wrap the up and down arrows into separate tags (span in my example) and include those within the TH tags for each column header.

    <th class="column_sort" id="name" data-order="desc" href="#">
        Title
        <span>&uarr;</span><span>&darr;</span>
    </th>
    

    Hide all the spans by default and we’ll target the others specifically by toggling between two other classes we’ll add to the TH that already has column_sort class.

    .column_sort{cursor:pointer}
    .column_sort span{display:none;}
    .sort_asc span:first-child{display:inline;}
    .sort_desc span:nth-child(2){display:inline;}
    

    Then for the javascript:

    $(document).on('click', '.column_sort', function(event){
    
        var $x = $(event.target);
        var ascending = $x.hasClass('sort_asc') ? true : false;
    
        // Remove arrows from any columns currently displaying them
        $('.column_sort.sort_asc').removeClass('sort_asc');
        $('.column_sort.sort_desc').removeClass('sort_desc');
    
        // Show the appropriate arrow
        if (ascending){     
            $x.addClass('sort_desc');   
        }else{
            $x.addClass('sort_asc');    
        }
      
    });
    

    https://jsfiddle.net/176hj8s0/

    Since you already have logic in place to handle ascend and descend order, you can just piggyback off that to determine which class is added.

    Login or Signup to reply.
  2. If you check your browser’s devtools console, I think you will see errors.

    If you check the docs for .remove(), it removes the matched element – in your case, it is trying to remove the whole <th>. If you pass a parameter, it should be a selector (not HTML), and it will filter the matched elements, not find nested elements. Because you are passing HTML, the .remove() call is generating an error and failing, so the img is never removed. Next time you click, a new one is added to the one that is already there.

    So you really want something like:

    $('#' + column_name + ' img').remove();
    

    This will match the <img> element inside the <th>, and remove it.

    Next problem – the order you add and remove elements is important. Eg: for the first click, you add a down arrow. If we now do the removal, the selector will match any image. That means we’ll remove both the old and the newly added images!

    So we need to take care to 1) Remove the old image first; 2) Add a new image.

    Here’s a working snippet – click the Run button to see it in action. I don’t have your images of course, so instead of <img> elements I used <span>s, but the idea is exactly the same.

    I also removed your AJAX code as that is not relevant to the problem.

    $(document).ready(function(){  
        var timesClicked = 0;
        $(document).on('click', '.column_sort', function(event){
            event.preventDefault();
            
            var column_name = $(this).attr("id");  
            timesClicked++;
               
            if (timesClicked % 2 == 1) {
                $('#' + column_name + ' span').remove();
                $('#' + column_name).append('<span> v</span>');   
    
            } else {
                $('#' + column_name + ' span').remove();
                $('#' + column_name).append('<span> ^</span>');
            };
        });  
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <table border='1' width='100%' style='border-collapse: collapse;' id='postsList'>
        <thead>
            <tr>
                <th>S.no</th>
                <th class="column_sort" id="name" data-order="desc" href="#">Title</th>
                <th class="column_sort" id="symbol" data-order="desc" href="#">Symbol</th>
            </tr>
         </thead>
         <tbody></tbody>
    </table>

    PS: as an alternative to adding and removing elements on every click, it might be a neater solution to simply toggle visibility of elements already on the page. Eg both arrow images are already on the page on page load, but with a "hidden" class. Every click then just toggles that class on/off. Maybe something like:

    $('#' + column_name + ' img').toggleClass('hidden');
    
    Login or Signup to reply.
  3. You can also use fontawesome icons instead of img for display of up and down arrows. Here’s a working example of how I do:
    Step 1. Use tag after column name

    <tr>
    <th>S.no</th>
    <th class="column_sort" id="name" data-order="desc" href="#">
        Title <i class="fas fa-angle-down rotate-icon pr-10"></i>
    </th>
    <th class="column_sort" id="symbol" data-order="desc" href="#">
        Symbol <i class="fas fa-angle-down rotate-icon pr-10"></i>
    </th>
    

    2.Jquery : First check which column is clicked and find class of icon tag and toggle it.

    <script type="text/javascript">
    $(document).on('click', '.column_sort', function(event) {
        event.preventDefault();
        if ($(this).find(".fas").hasClass('fa-angle-down')) {
            $(this).find(".fas").removeClass('fa-angle-down');
            $(this).find(".fas").addClass('fa-angle-up');
        } else {
            $(this).find(".fas").removeClass('fa-angle-up');
            $(this).find(".fas").addClass('fa-angle-down');
        }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search