skip to Main Content

TL;DR SUMMARY OF PROBLEM

AJAX will not use propery order and orderby parameters and instead sorts post by menu_order (posts section doesn’t even have post attributes set as true).

PROBLEM OVERVIEW

I am having a perplexing problem. I am in the process of creating a filtering system using AJAX and WordPress where the user will be able to filter through the posts by category and alter the order and orderby parameters to sort the posts by either ascending/descending dates and titles. I have the category filtering working, but the order and orderby parameters will not work.

Since the filtering works, I will only display the section correlated to the order and orderby parameters.

Important HTML:
This section is a drop down menu where the user can choose how they want the posts to be sorted.

<div class="laschf-sort">
   <select name="sort" id="archive-sort">
      <option hidden disabled selected value="default"> Sort by </option>
      <option value="date-desc">Date (Oldest - Newest)</option>
      <option value="date-asc">Date (Newest - Oldest)</option>
      <option value="title-asc">Title (A - Z)</option>
      <option value="title-desc">Title (Z - A)</option>
   </select>
</div>

On change, the value is passed through AJAX and determines the parameters that are used in the Query (following is the jQuery/AJAX):

$('#archive-sort').on('change', function() {
    filterNew = 1;
    var filterInput = $('#archive-filter').val();
    var sortInput = $('#archive-sort').val();
    var sortby = '';
    var sort = '';
    if(sortInput == 'date-asc') {
        sortby = 'date';
        sort = 'ASC';
    }else if(sortInput == 'date-desc') {
        sortby = 'date';
        sort = 'DESC';
    }else if(sortInput == 'title-asc') {
        sortby = 'title';
        sort = 'ASC';
    }else if(sortInput == 'title-desc') {
        sortby = 'title';
        sort = 'DESC';
    }else{
        sortby = 'date';
        sort = 'DESC';
    }
    console.log(filterInput);
    $.ajax({
        type: 'POST',
        url: ajax_url,
        dataType: 'json',
        data: {
            action: 'articles_filter_sort',
            paged: filterNew,
            cat: filterInput,
            sortby: sortby,
            sort: sort,
        },
        success: function (res) {
            console.log(res.query);
            $('.lasca-wrapper').empty();
            $('.lasca-read-more-wrap').empty();
            $('.lasca-wrapper').append(res.html);
            $('.lasca-read-more-wrap').append(res.readMore);
            if(filterNew >= res.max) {
                $('#aa-filter-load-btn').hide();
            }
        }
    });
});

As you can see, the values are taken from the drop down (and the filter is also taken from the other drop down select), then passed to a function (below), and upon success, the div which contains the posts are emptied and the new html is appended to the div.

The function (PHP):

/**
* SORT AND FILTER FUNCTION
*/

function articles_filter_sort() {
    $order = $_POST['sort'];
    $orderby = $_POST['sortby'];
    if($_POST['cat'] != null && $_POST['cat'] != 'all') {
        $args = [
            'post_type' => 'post',
            'posts_per_page' => '9',
            'status' => 'publish',
            'orderby' => $orderby,
            'order' => $order,
            'paged' => $_POST['paged'],
            'cat' => $_POST['cat'],
            //'suppress_filters' => true,
        ];
    }else{
        $args = [
            'post_type' => 'post',
            'posts_per_page' => '9',
            'status' => 'publish',
            'orderby' => $orderby,
            'order' => $order,
            'paged' => $_POST['paged'],
            //'suppress_filters' => true,
        ];
    }
    //remove_all_filters('posts_orderby');
    $filter_articles = new WP_Query($args);

    $response = '';
    $readMore = '';
    $max_pages = $filter_articles->max_num_pages;

    if($filter_articles->have_posts()) {
        while($filter_articles->have_posts()) : $filter_articles->the_post();
            $response .= '<div class="archive-article-card">

                                    <div class="aac-cat-share">
                                        <div class="aac-category">
                                            <span>' . get_the_category()[0]->name . '</span>
                                        </div>
                                        <button class="multi-btn">
                                            <i class="share-icon fa-light fa-share-nodes"></i>
                                            <ul>
                                                <li>
                                                    <a class="share-btn share-twitter" href="https://twitter.com/intent/tweet?text=' . rawurlencode(get_the_title()). ':%20' . get_permalink() . '"><div class="twitter-btn share-btn"><i class="fa-brands fa-twitter"></i></div></a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
                                                </li>
                                                <li>
                                                    <a class="share-btn share-fb" href="https://www.facebook.com/sharer/sharer.php?u=' . get_permalink() . '" title="Share on Facebook" target="_blank"><div class="fb-btn share-btn"><i class="fa-brands fa-square-facebook"></i></div></a>
                                                </li>
                                                <li>
                                                    <a class="share-btn share-linkedin" href="https://linkedin.com/shareArticle?url=' . get_permalink() . '" target="_blank"><div class="linkedin-btn share-btn"><i class="fa-brands fa-linkedin"></i></div></a>
                                                </li>
                                            </ul>
                                        </button>
                                    </div>
                            
                            <div class="aac-content">
                                <div class="aacc-date">' .
                                    get_the_date('d.m.Y')
                                . '</div>
                                <div class="aacc-title">' .
                                    get_the_title()
                                . '</div>
                                <div class="aacc-excerpt">' .
                                    bl_get_excerpt()
                                . '</div>
                            </div>
                            <div class="aac-post-read-more-wrap">
                                <div class="aacprm-button">
                                    <a href="' . get_post_permalink() .'">
                                        <button>View Details <span>⟶</span></button>
                                    </a>
                                </div>
                            </div>
                        </div>';
        endwhile;
        $readMore .= '<button id="aa-filter-load-btn">View More</button>';
    }else{
        $response .= 'No Posts Found';
    }

    $result = [
        'max' => $max_pages,
        'html' => $response,
        'readMore' => $readMore,
        'query' => $filter_articles->query,
        'orderby' => $orderby,
        'order' => $order,
        'args' => $args
    ];

    echo json_encode($result);
    exit;
}
add_action('wp_ajax_articles_filter_sort', 'articles_filter_sort');
add_action('wp_ajax_nopriv_articles_filter_sort', 'articles_filter_sort');

So as you can see, the function checks to see if there is a filter and determines which argument to use for the Query. The Query then determines the number of pages in the search (this is used for the read more button), and generates the posts using the response html. This response will also send the html for the read more button as well.

After the html is generated, the function then collects all the results that is sent back to AJAX to be appended to the html.

EXPECTED RESULTS

I expect this to work. This function is used for the filter AJAX as well, and works perfectly. The sorting functionality should be sending the order and orderby arguments and it should be used in the query.

WHAT IS HAPPENING

As you can see, I actually output the query in the results and I have it console.log()’d within the AJAX success. When change the value in the drop down, I can actually see the query used by the AJAX, and it indicates that it is (should be) using the correct parameters (as in I can see "orderby" => "date" and "order "DESC" if I choose "Sort by Date Oldest to Newest" within the Query).

However, if I output queryparams as well as the query, the queryparams indicates that orderby is "menu_order" for every sort, despite the query not using it.

WHAT I’ve DONE

So as you can see, I have done troubleshooting to figure out what is happening behind the scenes. And in my research, the only thing I could find is that AJAX uses admin filtering which is causing the menu_order to be used instead of the proper parameters.

I have tried used 'suppress_filters' => true in the argument, but that did not solve the problem.

I have also tried running the function remove_all_filters('posts_orderby'); before the Query call, and that also did not work.

Does anyone know a way for me to ensure the proper parameters are being used in the output instead of menu_order?

2

Answers


  1. Chosen as BEST ANSWER

    So I found the solution. Before the Query call I ran:

    remove_all_actions('pre_get_posts');
    

    This fixed the problem. Phew; such an easy solution for something that was annoying me to no end.


  2. Can’t comment your post so writing in answer.

    1. why you add default option to select when you sorting records by date by default? Just select it
    2. don’t use that if statement in js, you can simply pass select value as it is and in back-end with explode get first and second param for filtering
    3. create you args without cat, and then check if it exists in $_post and append to array
    4. instead of writing html in function simply create separate template for this and get it with get_template_part, wrap it with ob_start and you’ll get much cleaner code
    5. for return use function wp_send_json_success

    Hope this will help you make your code cleaner and nicer to read

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search