javascript - Ajax filter for categories in Wordpress - Stack Overflow

I'm building a site with Wordpress. I've created a filter with the default category to displa

I'm building a site with Wordpress. I've created a filter with the default category to display the posts. The filter uses checkboxes, so the user can select one or multiple categories.

The issue is, when I select a category it displays all the posts. I think the problem comes from the Javascript code.

I would also like that when none of the category is selected, it displays all the posts.

The PHP filter:

<?php
if( $terms = get_terms( array( 'taxonomy' => 'category', 'parent' => 0, 'hide_empty' => true ) ) ) :

    echo '
    <form data-ajax-url="'. get_site_url()  .'/wp-admin/admin-ajax.php" method="POST" id="filter" class="js-filter">
        <ul class="js-filter-list">';

            foreach( $terms as $term ) :

                $term_id = $term->term_id;
                $term_name = $term->name;
                $term_slug = $term->slug;

                $term_color = get_term_meta( $term_id, 'post-category-settings__color', true );

                echo '
                <li class="js-filter-item js-filter-term" data-slug="'. esc_attr( $term_slug ) .'">
                    <input type="checkbox" class="c-filter__check" id="' . esc_attr($term_id) . '" name="' . esc_attr($term_id) . '" />
                    <label class="semi-medium" for="' . esc_attr($term_id) . '"><span></span>' . esc_html($term_name) . '</label>
                </li>';
            endforeach;

    echo '
        </ul>
        <input type="hidden" name="action" value="filterpost">
    </form>';
endif;
?>

<div class="js-container"></div>

The JS:

if (document.querySelector('.js-filter')) {
    const ajax_url = document.querySelector(".js-filter").dataset.ajaxUrl;
    let filterBtn = document.querySelectorAll('.js-filter-term');

    var i;
    for( i = 0; i < filterBtn.length; i++ ){
        filterBtn[i].addEventListener('change', function(){

            const containerTerm = document.querySelector(".js-container");
            const data = new FormData();

            let term_slug = this.dataset.slug;

            data.append( 'action', 'filterpost' );
            data.append( 'category', term_slug );

            fetch(ajax_url, {
            method: "POST",
            body: data
            })
            .then((response) => response.text())
            .then((data) => {
            if (data) {
                containerTerm.innerHTML=data;
            }
            })
            .catch((error) => {

            });
        });
    };
}

The AJAX handler:

<?php
function site_filter_post() {

    if( $terms = get_terms( array( 'taxonomy' => 'category' ) ) ) :
        $terms_list = array();

        foreach( $terms as $term ) {
        if( isset( $_POST[$term->term_id ] ) && $_POST[$term->term_id] == 'on' )
         $terms_list[] = $term->slug;
        }
    endif;

    $tax_query = array( 'relation' => 'AND' );
  
    if ( ! empty( $terms_list ) ) {
        $tax_query[] = array(
            array(
            'taxonomy'      => 'category',
            'field'         => 'slug',
            'terms'         => $terms_list,
            )
        );
    }
  
    $args = array(
        'post_type'         => 'post',
        'posts_per_page'    => -1,
        'post_status'       => 'publish',
        'orderby'           => 'date',
        'tax_query'         => $tax_query
        
    );

    $query = new WP_Query( $args );
  
    if($query->have_posts()) {

        while($query->have_posts()) : $query->the_post();

            get_template_part( 'template-parts/content', 'archive' );
  
        endwhile;
  
    } else {

        echo 'No result.';

    }
  
    exit;
}
add_action('wp_ajax_filterpost', 'site_filter_post');
add_action('wp_ajax_nopriv_filterpost', 'site_filter_post');
?>

Thank you.

I'm building a site with Wordpress. I've created a filter with the default category to display the posts. The filter uses checkboxes, so the user can select one or multiple categories.

The issue is, when I select a category it displays all the posts. I think the problem comes from the Javascript code.

I would also like that when none of the category is selected, it displays all the posts.

The PHP filter:

<?php
if( $terms = get_terms( array( 'taxonomy' => 'category', 'parent' => 0, 'hide_empty' => true ) ) ) :

    echo '
    <form data-ajax-url="'. get_site_url()  .'/wp-admin/admin-ajax.php" method="POST" id="filter" class="js-filter">
        <ul class="js-filter-list">';

            foreach( $terms as $term ) :

                $term_id = $term->term_id;
                $term_name = $term->name;
                $term_slug = $term->slug;

                $term_color = get_term_meta( $term_id, 'post-category-settings__color', true );

                echo '
                <li class="js-filter-item js-filter-term" data-slug="'. esc_attr( $term_slug ) .'">
                    <input type="checkbox" class="c-filter__check" id="' . esc_attr($term_id) . '" name="' . esc_attr($term_id) . '" />
                    <label class="semi-medium" for="' . esc_attr($term_id) . '"><span></span>' . esc_html($term_name) . '</label>
                </li>';
            endforeach;

    echo '
        </ul>
        <input type="hidden" name="action" value="filterpost">
    </form>';
endif;
?>

<div class="js-container"></div>

The JS:

if (document.querySelector('.js-filter')) {
    const ajax_url = document.querySelector(".js-filter").dataset.ajaxUrl;
    let filterBtn = document.querySelectorAll('.js-filter-term');

    var i;
    for( i = 0; i < filterBtn.length; i++ ){
        filterBtn[i].addEventListener('change', function(){

            const containerTerm = document.querySelector(".js-container");
            const data = new FormData();

            let term_slug = this.dataset.slug;

            data.append( 'action', 'filterpost' );
            data.append( 'category', term_slug );

            fetch(ajax_url, {
            method: "POST",
            body: data
            })
            .then((response) => response.text())
            .then((data) => {
            if (data) {
                containerTerm.innerHTML=data;
            }
            })
            .catch((error) => {

            });
        });
    };
}

The AJAX handler:

<?php
function site_filter_post() {

    if( $terms = get_terms( array( 'taxonomy' => 'category' ) ) ) :
        $terms_list = array();

        foreach( $terms as $term ) {
        if( isset( $_POST[$term->term_id ] ) && $_POST[$term->term_id] == 'on' )
         $terms_list[] = $term->slug;
        }
    endif;

    $tax_query = array( 'relation' => 'AND' );
  
    if ( ! empty( $terms_list ) ) {
        $tax_query[] = array(
            array(
            'taxonomy'      => 'category',
            'field'         => 'slug',
            'terms'         => $terms_list,
            )
        );
    }
  
    $args = array(
        'post_type'         => 'post',
        'posts_per_page'    => -1,
        'post_status'       => 'publish',
        'orderby'           => 'date',
        'tax_query'         => $tax_query
        
    );

    $query = new WP_Query( $args );
  
    if($query->have_posts()) {

        while($query->have_posts()) : $query->the_post();

            get_template_part( 'template-parts/content', 'archive' );
  
        endwhile;
  
    } else {

        echo 'No result.';

    }
  
    exit;
}
add_action('wp_ajax_filterpost', 'site_filter_post');
add_action('wp_ajax_nopriv_filterpost', 'site_filter_post');
?>

Thank you.

Share Improve this question edited Jan 17 at 18:33 Mathieu Préaud asked Jan 17 at 16:55 Mathieu PréaudMathieu Préaud 4511 gold badge5 silver badges18 bronze badges 2
  • Yes you're right, I just modified it. However the issue is here. – Mathieu Préaud Commented Jan 17 at 17:14
  • My two cents, skip AJAX for now and stick to an HTML form talking to PHP/WordPress. You can usually more easily see warning messages and it is also easier to var_dump($_POST) to inspect things. Once you get the HTML form working you can then "upgrade" it to AJAX. – Chris Haas Commented Jan 17 at 18:31
Add a comment  | 

1 Answer 1

Reset to default 1

You're right, everything seems to work except for the JavaScript code.

  1. FormData should be constructed using the <form> element, as it already contains all the necessary values, including term IDs and the name of an action.
  2. It's enough to add a single change listener to the <form> instead of having multiple listeners, each responsible for just one checkbox.
const filterForm = document.querySelector('.js-filter');
if (filterForm) {
    const ajax_url = filterForm.dataset.ajaxUrl;
    const containerTerm = document.querySelector(".js-container");

    filterForm.addEventListener('change', function () {
        const data = new FormData(filterForm);

        fetch(ajax_url, {
            method: 'POST',
            body: data
        })
        .then((response) => response.text())
        .then((data) => {
            if (data) {
                containerTerm.innerHTML = data;
            }
        })
        .catch((error) => {
            console.error(error);
        });
    });
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745353934a4624004.html

相关推荐

  • javascript - Ajax filter for categories in Wordpress - Stack Overflow

    I'm building a site with Wordpress. I've created a filter with the default category to displa

    2小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信