1

I'm trying to code an ajax custom post filter but the result seems like it's not filtering, and I'm not sure where I did wrong. I'll provide the revelant code below.

archive-projetos.php

<div class="categories">
    <ul>
        <li><a href="" class="js-filter-item">Todos</a></li>
        <?php
        $cat_args = array(
            'exclude' => array(1),
            'option_all' => 'All',
            'taxonomy' => 'Tipos de Construção'
        );
        $categories = get_categories($cat_args);

        foreach($categories as $cat): ?>
            <li><a class="js-filter-item" href="<?= get_category_link($cat->term_id);?>"><?= $cat->name;?></a></li>
        <?php endforeach;?>
    </ul>
</div>
<div class="content-wrapper js-filter row">
    <?php
    $args = array (
        'post_type' => array('projetos'),
        'post_status' => array('publish')
    );

    $query = new WP_Query($args);

    if($query->have_posts()):
        while ($query->have_posts()) : $query->the_post();?>
        <div class="post-thumbnail-container col-sm">
            <a href="<?php the_permalink();?>">
                <div class="thumbnail-container"><?php the_post_thumbnail();?></div>
                <div class="title-overlay"><?php the_title();?></div>
            </a>
        </div>
        <?php endwhile; else: endif; wp_reset_postdata();?>
</div>

filter.js

(function($){
    $(document).ready(function(){
        $(document).on('click', '.js-filter-item', function(e){
            e.preventDefault();
            
            var category =$(this).data('category');

            $.ajax({
                url: wpajax.ajaxurl,
                data: {action: 'filter', category: category},
                type: 'post',
                success: function(result) {
                    $('.js-filter').html(result);
                },
                error: function(result) {
                    console.warn(result);
                }
            });
        });
    });
})(jQuery);

functions.php

function load_scripts() {
    wp_enqueue_script('ajax', get_template_directory_uri() . '/js/filter.js', array ('jquery'), NULL, true);

    wp_localize_script('ajax','wpajax',
        array('ajaxurl' => admin_url('admin-ajax.php'))
    );
}

add_action('wp_enqueue_scripts', 'load_scripts');

add_action('wp_ajax_nopriv_filter', 'filter_ajax');
add_action('wp_ajax_filter', 'filter_ajax');

function filter_ajax() {

    $category = $_POST['projetos'];

    $args = array (
        'post_type' => array('projetos'),
        'post_status' => array('publish')
    );

    $query = new WP_Query($args);

    if(isset($category)) {
        $args['category__in'] = array($category);
    }

    if($query->have_posts()):
        while ($query->have_posts()) : $query->the_post();?>
        <div class="post-thumbnail-container col-sm">
            <a href="<?php the_permalink();?>">
                <div class="thumbnail-container"><?php the_post_thumbnail();?></div>
                <div class="title-overlay"><?php the_title();?></div>
            </a>
        </div>
        <?php endwhile; else: endif; wp_reset_postdata();

    die();
}

I don't think it would be necessary to include the custom post and category but there it goes as well:

function projetos()
{
    $args = array(
        'labels' => array(
            'name'=> 'Projetos',
            'singular_name'=>'Projeto'
        ),
        'public' => true,
        'has_archive' => true,
        'menu_icon' => 'dashicons-category',
        'supports' => array('title','editor','thumbnail')
    );
    register_post_type('projetos', $args);
}
add_action('init', 'projetos');

function tipos_construcao() 
{

    $args = array(
        'labels' => array (
            'name' => 'Tipos de Construção',
            'singular_name'=>'Tipo de Construção'
        ),
        'public'=> true,
        'hierarchical'=> true
        );
    register_taxonomy('Tipos de Construção',array('projetos'), $args);
}
add_action('init', 'tipos_construcao');

Any help would be appreciated! I've been trying several solutions and tried to browse other websites but to no solution.

I did console.log(result) in the filter.js to check what was the result, and it just doesn't filter, the result is all the posts.

Thank you, once again!

4
  • 1
    From what I see, your <a> in the foreach loop in archive-projetos.php which has the CSS class js-filter-item needs to have a data-category attribute. E.g. Add data-category="<?php echo $cat->term_id; ?>" to that <a> tag.
    – Sally CJ
    Commented Jan 20, 2021 at 6:10
  • @SallyCJ thank you for your reply! Adding the data-category attribute to the <a> tag did not solve the problem unfortunely, It still doesn't filter out the posts. But I thank you for your reply Commented Jan 20, 2021 at 12:28
  • 1
    I forgot to say, in addition to that data-category, in your filter_ajax() function, switch the position of the $query = new WP_Query($args) with the if(isset($category)) { ... }.
    – Sally CJ
    Commented Jan 20, 2021 at 12:55
  • Thank you once again for your assistance as the solutions you propose are seriously short comings on my part and it makes sense. I did so as you proposed, but sadly, still does not work, I also tried messing with the $category = $_POST['projetos']; as maybe I thought 'projetos' was the culprit behind displaying all the posts, so I tried to change it to 'category' but the output is empty. while if I use 'projetos' the output is all the posts, also tried to erase the if(isset($category)) and place the category__in directly in the array above, but the output looks to be the same. Commented Jan 20, 2021 at 13:24

1 Answer 1

0

How to make your AJAX filter works properly:

  1. As I said in the comments, add the data-category attribute to the <a> having the CSS class js-filter-item in the foreach loop in your archive-projetos.php template:

    // * Wrapped for brevity.
    foreach ( $categories as $cat ) : ?>
        <li><a class="js-filter-item"
            href="<?= get_category_link( $cat->term_id ); ?>"
            data-category="<?= $cat->term_id; ?>"
        ><?= $cat->name; ?></a></li>
    <?php endforeach; ?>
    

    And if you wonder why add that attribute, then it's because in filter.js, the script is reading the category ID via $(this).data('category') which is equivalent to $( this ).attr( 'data-category' ).

  2. In the filter_ajax() function in functions.php, replace this:

    $query = new WP_Query($args);
    
    if(isset($category)) {
        $args['category__in'] = array($category);
    }
    

    with this:

    if ( ! empty( $category ) ) {
        $args['tax_query'] = array(
            array(
                'taxonomy' => 'Tipos de Construção',
                'terms'    => $category,
            ),
        );
    }
    
    $query = new WP_Query( $args );
    

    I.e. Switch the position (of the new WP_Query() call and the if block) and then use the tax_query parameter and not category__in which is for the default category taxonomy only.

  3. Also in that filter_ajax() function, replace the $category = $_POST['projetos']; with $category = $_POST['category']; because your JS script is sending the category ID in a (POST) input named category and not projetos.

    However, you should always check if an array item is actually set before attempting to use it, so you would want to use $category = $_POST['category'] ?? ''; or the old way (prior to PHP 7): $category = isset( $_POST['category'] ) ? $_POST['category'] : '';.

Additional Notes

Even though the Tipos de Construção does work as the taxonomy name, i.e. the first parameter you pass to register_taxonomy(), you should actually use a slug like tipos_de_construcao because the documentation says:

$taxonomy is the name of the taxonomy. Name should only contain lowercase letters and the underscore character, and not be more than 32 characters long (database structure restriction). Default: None

So you should try to fix the taxonomy name, i.e. use a slug. It will take time, but it will be a better option in the long run. =)

2
  • 1
    Thank you for your help, it works finally! I can understand the problem now and what I did wrong, also for future reference for anyone seeing this, the line $category = $_POST['projetos'];is wrong as well 'projetos' should be replaced by 'category' as it was a oversight on my part as well. Thank you Sally once again for your help, you have been amazing. Commented Jan 21, 2021 at 12:19
  • Glad my answer helped you! And I've added that category thing to my answer. :) Have a nice weekend!
    – Sally CJ
    Commented Jan 23, 2021 at 4:25

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.