Skip to main content

AJAX Post Filtering In WordPress

By August 16, 2017Blog, Sage, Wordpress
WordPress Tutorials by Allure Web Solutions

In this post I’m describing the process for AJAX post filtering All credits go to Misha Rudrastyh. My contribution is to make add two features. The first is making it work with Sage 9 namespacing. The second is to make the filtering working without pressing a submit button. The example below is for the Sage 9 them, but can easily be modified to work with any theme.

The Post Filter

This goes into app/helpers.php.

/**
 * Post Filter
 */
if (!function_exists(__NAMESPACE__ . '\\filter_posts')) :
    function filter_posts()
    {
        ?>
        <div class="post-filter">
            <form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
                <p>FILTER POSTS BY</p>
                <?php wp_dropdown_categories(
                    array(
                        'orderby' => 'name',
                        'show_count' => false,
                        'show_option_all' => 'All Categories',
                        'hide_if_empty' => true,
                        'name' => 'categoryfilter',
                    ))
                ?>
                <input type="hidden" name="action" value="myfilter">
            </form>
        </div>
        <?php
    }
endif;

The Filtering Function

This goes into app/helpers.php.

/**
 * Post filter function
 */
function post_filter_function()
{
    $args = array(
        'orderby' => 'date', // we will sort posts by date
        'order' => $_POST['date'] // ASC or DESC
    );

    // for taxonomies / categories
    if (isset($_POST['categoryfilter']))
        $args['tax_query'] = array(
            array(
                'taxonomy' => 'category',
                'field' => 'id',
                'terms' => $_POST['categoryfilter']
            )
        );

    $query = new \WP_Query($args);

    if ($query->have_posts()) :
        echo '<div class="row">';
        while ($query->have_posts()): $query->the_post();
            ?>
            <article <?= post_class(); ?>>
                <div class="row no-gutters">
                    <?php $post_image = get_the_post_thumbnail($post_id, 'thumbnail', array('class' => 'post-image'));
                    if (!empty($post_image))
                        echo '<div class="entry entry-image">' . $post_image . '</div>'
                    ?>

                    <div class="entry entry-content">
                        <header>
                            <time class="updated" datetime="<?= get_post_time('c', true); ?>"><?= get_the_date() ?>
                            </time>
                            <h2 class="entry-title"><a href="<?= get_permalink(); ?>"><?= get_the_title() ?></a></h2>
                            <p class="byline author vcard">
                                <?= __('By:', 'sage'); ?> <a
                                        href="<?= get_author_posts_url(get_the_author_meta('ID')); ?>"
                                        rel="author"
                                        class="fn">
                                    <?= get_the_author(); ?>
                                </a>
                            </p>
                        </header>
                        <div class="entry-summary">
                            <?= the_excerpt(); ?>
                        </div>
                    </div>
                </div>
            </article>
            <?php
        endwhile;
        echo '</div>';
        wp_reset_postdata();
    else :
        echo 'No posts found';
    endif;

    die();
}

add_action('wp_ajax_myfilter', __NAMESPACE__ . '\\post_filter_function');
add_action('wp_ajax_nopriv_myfilter', __NAMESPACE__ . '\\post_filter_function');

The Template & Loop

This example is for sage 9 and inside resources/views/index.blade.php.

{!! App\filter_posts() !!}

<div id="blog-posts" class="list">
    <div class="row">
        @while (have_posts()) @php(the_post())
        @include ('partials.content-'.(get_post_type() === 'post' ?: get_post_type()))
        @endwhile
    </div>
</div>

The JavaScript

/**
 * AJAX filter functionality
 */
$('#categoryfilter').change(function () {
    var filter = $('#filter');
    $.ajax({
        url: filter.attr('action'),
        data: filter.serialize(), // form data
        type: filter.attr('method'), // POST
        beforeSend: function () {
            // check if all categories is selected
            if (filter.serialize().indexOf('categoryfilter=0') !== -1) {
                location.reload();
            }
        },
        success: function (data) {
            $('#blog-posts').html(data); // insert data
        },
    });
    return false;
});

 

allure

Author allure

More posts by allure

Join the discussion 9 Comments

  • dave says:

    Thanks for the tutorial. One issue I’m having is the admin-ajax.php is returning with a console error of ” the server responded with a status of 400 (Bad Request)”

    Any idea how to fix it?

    • Mike Doubintchik says:

      That error could mean many things. It’s impossible to tell without looking at your code. If you aren’t using Sage 9, I recommend looking at the original article I mention at the top of the post.

      • dave says:

        Hi Mike, thanks for the reply. Im using Sage 9 and the same code for the Ajax function. I’ve also tried wp_localize_script to use the admin-ajax.php on ajax url.

        The other 2 PHP functions are very similar except im using a CPT Taxonomies

        • Mike Doubintchik says:

          Yeah, without seeing the code I cannot help much. This would require some troubleshooting.

          • dave says:

            Sorry Mike, thought I’d ask just incase you knew of anything top of your head, also didn’t want to just paste all the code down in the comments.

            I have pasted the functions on the below link

            https://codeshare.io/2j7dwM

            The markup for the posts are different but been scratching my head on how to fix this. Its a website I’ve inherited and first time using Sage

          • Mike Doubintchik says:

            One thing I noticed is that your ajax actions needs to match the hidden input on the filter. So change `wp_ajax_post_filter_function` to `wp_ajax_myfilter` and `wp_ajax_nopriv_post_filter_function`

            If that doesn’t solve it, I’m not sure what else could be the issue without active troubleshooting (ie. getting into the code).

          • dave says:

            Ah OK, I tried that previously and just again now but still getting the 400 bad request for admin-ajax. No worries, thanks for your time.

  • Mattia says:

    Thanks for the tutorial, I was looking for Sage specific tutorials, and I found your blog and I fell in love <3
    I am even using your custom Numeric Page Navigation {!! App\page_navi() !!}.
    Do you know how I can include the pagination in the blog with this AJAX post-filtering?
    right now I can see the pagination only in the "all category" page, but as soon as I change the category, the pagination is not showing anymore.
    In the wp-admin I set "Blog pages show at most" to a very small number for a testing purpose, but I can't see the pagination, only in the "all category" page.

    could you please point me in the right direction?

    thanks a lot

    • Mike Doubintchik says:

      Looks like you may need personalized help. Feel free to reach out through the contact form on my site and we’ll go from there.

Leave a Reply

Designed by

best down free | web phu nu so | toc dep 2017