0

TL;DR SUMMARY OF PROBLEM

AJAX will not use the proper order and orderby parameters given, 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>&#10230;</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.

Question

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

2
  • have you searched your codebase for cases of pre_get_posts? You shouldn't need to take any additional steps if pre_get_posts hooks are built correctly, especially the kind of steps you put in your answer
    – Tom J Nowell
    Commented Feb 22, 2023 at 15:02
  • I have that set for two custom post types, and there is an if statement around the hook which checks to make sure the query is for the specific post type, but it seems like it was interrupting. I actually just posted that solution. Commented Feb 22, 2023 at 15:05

1 Answer 1

1

Found the solution in case anyone is having the same problem. Before the Query call I ran:

remove_all_actions('pre_get_posts');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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