Как в ajax кнопку «Показать еще» передать выбранные категории в фильтре?

Ссылка скопирована
1 ответ

Нужно чтобы в кнопку передавались выбранные категории в ajax фильтре, чтобы при нажатии "показать еще" подгружались записи только из выбранных в фильтре категориях

Код кнопки:
Обработчик

<?php function misha_my_load_more_scripts() {   	global $wp_query;    	// In most cases it is already included on the page and this line can be removed 	wp_enqueue_script('jquery');   	// register our main script but do not enqueue it yet 	wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/assets/js/myloadmore.js', array('jquery') );   	// now the most interesting part 	// we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP 	// you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script() 	wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array( 		'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX 		'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here 		'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1, 		'max_page' => $wp_query->max_num_pages, 	) );    	wp_enqueue_script( 'my_loadmore' ); }   add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' );  function misha_loadmore_ajax_handler(){   	$args = json_decode( stripslashes( $_POST['query'] ), true ); 	$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded 	$args['post_status'] = 'publish';   	// it is always better to use WP_Query but not here 	query_posts( $args );   	if( have_posts() ) :         woocommerce_product_loop_start(); 		// run the loop 		while( have_posts() ): the_post();   			// look into your theme code how the posts are inserted, but you can use your own HTML of course 			// do you remember? - my example is adapted for Twenty Seventeen theme 			    wc_get_template_part( 'content', 'product' ); 			// for the test purposes comment the line above and uncomment the below one 			// the_title();     		endwhile;         woocommerce_product_loop_end(); 	endif; 	die; // here we exit the script and even no wp_reset_query() required! }       add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action} add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}

<?php function misha_my_load_more_scripts() { global $wp_query; // In most cases it is already included on the page and this line can be removed wp_enqueue_script('jquery'); // register our main script but do not enqueue it yet wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/assets/js/myloadmore.js', array('jquery') ); // now the most interesting part // we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP // you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script() wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array( 'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX 'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here 'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1, 'max_page' => $wp_query->max_num_pages, ) ); wp_enqueue_script( 'my_loadmore' ); } add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' ); function misha_loadmore_ajax_handler(){ $args = json_decode( stripslashes( $_POST['query'] ), true ); $args['paged'] = $_POST['page'] + 1; // we need next page to be loaded $args['post_status'] = 'publish'; // it is always better to use WP_Query but not here query_posts( $args ); if( have_posts() ) : woocommerce_product_loop_start(); // run the loop while( have_posts() ): the_post(); // look into your theme code how the posts are inserted, but you can use your own HTML of course // do you remember? - my example is adapted for Twenty Seventeen theme wc_get_template_part( 'content', 'product' ); // for the test purposes comment the line above and uncomment the below one // the_title(); endwhile; woocommerce_product_loop_end(); endif; die; // here we exit the script and even no wp_reset_query() required! } add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action} add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}

Ajax

jQuery(function ($) {     // use jQuery code inside this to avoid "$ is not defined" error     $(".btn--more").click(function () {         var button = $(this),             data = {                 action: "loadmore",                 query: misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function                 page: misha_loadmore_params.current_page,             };          $.ajax({             // you can also use $.post here             url: misha_loadmore_params.ajaxurl, // AJAX handler             data: data,             type: "POST",             beforeSend: function (xhr) {                 button.html('Загрузка... <svg class="icon icon-load icon-load--anim"><use xlink:href="#icon-load"></use></svg>'); // change the button text, you can also add a preloader image             },             success: function (data) {                 if (data) {                     button.html('Показать ещё <svg class="icon icon-load"><use xlink:href="#icon-load"></use></svg>').prev().after(data); // insert new posts                     misha_loadmore_params.current_page++;                      if (misha_loadmore_params.current_page == misha_loadmore_params.max_page) button.remove(); // if last page, remove the button                      // you can also fire the "post-load" event here if you use a plugin that requires it                     // $( document.body ).trigger( 'post-load' );                 } else {                     button.remove(); // if no data, remove the button as well                 }             },         });     }); });

jQuery(function ($) { // use jQuery code inside this to avoid "$ is not defined" error $(".btn--more").click(function () { var button = $(this), data = { action: "loadmore", query: misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function page: misha_loadmore_params.current_page, }; $.ajax({ // you can also use $.post here url: misha_loadmore_params.ajaxurl, // AJAX handler data: data, type: "POST", beforeSend: function (xhr) { button.html('Загрузка... <svg class="icon icon-load icon-load--anim"><use xlink:href="#icon-load"></use></svg>'); // change the button text, you can also add a preloader image }, success: function (data) { if (data) { button.html('Показать ещё <svg class="icon icon-load"><use xlink:href="#icon-load"></use></svg>').prev().after(data); // insert new posts misha_loadmore_params.current_page++; if (misha_loadmore_params.current_page == misha_loadmore_params.max_page) button.remove(); // if last page, remove the button // you can also fire the "post-load" event here if you use a plugin that requires it // $( document.body ).trigger( 'post-load' ); } else { button.remove(); // if no data, remove the button as well } }, }); }); });

Вывод кнопки

global $wp_query; // you can remove this line if everything works for you      // don't display the button if there are not enough posts     if (  $wp_query->max_num_pages > 1 )         echo '<div class="btn--more">Показать ещё <svg class="icon icon-load"><use xlink:href="#icon-load"></use></svg></div>'; // you can use <a> as well     }

global $wp_query; // you can remove this line if everything works for you // don't display the button if there are not enough posts if ( $wp_query->max_num_pages > 1 ) echo '<div class="btn--more">Показать ещё <svg class="icon icon-load"><use xlink:href="#icon-load"></use></svg></div>'; // you can use <a> as well }

Код фильтра:
Обработчик

function perviy_filter() { 	global $wp_query;       $args = array(         'post_type' => 'product',         'post_status' => 'publish',         'posts_per_page' => 4,         'tax_query' => array(             'relation' => 'AND',             array(                 'taxonomy' => 'product_visibility',                 'field' => 'name',                 'terms' => 'exclude-from-catalog',                 'operator' => 'NOT IN',             )         ),     );      // Категории товаров     $product_cats = ! empty( $_POST[ 'product_cats' ] ) && $_POST[ 'product_cats' ] ? $_POST [ 'product_cats' ] : array();          if( $product_cats ) {         $args['tax_query'][] = array(             'taxonomy' => 'product_cat',             'terms' => $product_cats         );     }     echo '<pre>';     print_r($_POST['term_id']);     echo '</pre>';     $query = new WP_Query( $args );      if( $query->have_posts() ) {         while( $query->have_posts() ): $query->the_post();             wc_get_template_part( 'content', 'product' );         endwhile;     }       die(); }

function perviy_filter() { global $wp_query; $args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => 4, 'tax_query' => array( 'relation' => 'AND', array( 'taxonomy' => 'product_visibility', 'field' => 'name', 'terms' => 'exclude-from-catalog', 'operator' => 'NOT IN', ) ), ); // Категории товаров $product_cats = ! empty( $_POST[ 'product_cats' ] ) && $_POST[ 'product_cats' ] ? $_POST [ 'product_cats' ] : array(); if( $product_cats ) { $args['tax_query'][] = array( 'taxonomy' => 'product_cat', 'terms' => $product_cats ); } echo '<pre>'; print_r($_POST['term_id']); echo '</pre>'; $query = new WP_Query( $args ); if( $query->have_posts() ) { while( $query->have_posts() ): $query->the_post(); wc_get_template_part( 'content', 'product' ); endwhile; } die(); }

Ajax

jQuery(function ($) {     $("#ajax-filter").submit(function (event) {         event.preventDefault();          const form = $(this);          $.ajax({             type: "POST",             url: woocommerce_params.ajax_url,             data: form.serialize(),             beforeSend: function (xhr) {                 $(".site-main").block({                     message: null,                     overlayCSS: {                         background: "#fff",                         opacity: 0.3,                     },                 });             },             success: function (data) {                 $("ul.products").html(data);                 $(".site-main").unblock();             },         });     });     $('#ajax-filter input[type="checkbox"]').change(function () {         $("#ajax-filter").submit();     }); });

jQuery(function ($) { $("#ajax-filter").submit(function (event) { event.preventDefault(); const form = $(this); $.ajax({ type: "POST", url: woocommerce_params.ajax_url, data: form.serialize(), beforeSend: function (xhr) { $(".site-main").block({ message: null, overlayCSS: { background: "#fff", opacity: 0.3, }, }); }, success: function (data) { $("ul.products").html(data); $(".site-main").unblock(); }, }); }); $('#ajax-filter input[type="checkbox"]').change(function () { $("#ajax-filter").submit(); }); });

Форма с фильтром

<form action="" method="POST" id="ajax-filter">                 <?php $product_categories = get_terms( array( 'taxonomy' => 'product_cat', 'hide_empty' => true ) );                 if( $product_categories ) : ?>                 <ul class="category">                     <?php foreach( $product_categories as $product_category ) : ?>                     <li>                         <input type="checkbox" name="product_cats[]" id="product-cat-<?php echo absint( $product_category->term_id ) ?>" value="<?php echo absint( $product_category->term_id ) ?>">                         <label for="product-cat-<?php echo absint( $product_category->term_id ) ?>"><?php echo esc_html( $product_category->name ); ?></label>                     </li>                     <?php endforeach; ?>                 </ul>                 <?php endif; ?>                 <input type="hidden" name="action" value="perviyfilter">               </form>

<form action="" method="POST" id="ajax-filter"> <?php $product_categories = get_terms( array( 'taxonomy' => 'product_cat', 'hide_empty' => true ) ); if( $product_categories ) : ?> <ul class="category"> <?php foreach( $product_categories as $product_category ) : ?> <li> <input type="checkbox" name="product_cats[]" id="product-cat-<?php echo absint( $product_category->term_id ) ?>" value="<?php echo absint( $product_category->term_id ) ?>"> <label for="product-cat-<?php echo absint( $product_category->term_id ) ?>"><?php echo esc_html( $product_category->name ); ?></label> </li> <?php endforeach; ?> </ul> <?php endif; ?> <input type="hidden" name="action" value="perviyfilter"> </form>

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
WordPress-редакция Ответ

Для кнопки «Показать ещё» нужно хранить текущее состояние фильтра на фронте и отправлять его вместе с AJAX-запросом. Если пользователь выбрал категории, JS должен собрать их ID/slug и передать в $.ajax(). PHP-обработчик уже строит tax_query по этим значениям.

Пример сбора выбранных категорий:

function getSelectedCategories() {
  return $('.filter-category:checked').map(function () {
    return $(this).val();
  }).get();
}
 
$('.load-more').on('click', function () {
  $.ajax({
    url: loadmore_params.ajaxurl,
    type: 'POST',
    data: {
      action: 'load_more_posts',
      page: loadmore_params.current_page,
      categories: getSelectedCategories()
    },
    success: function (html) {
      $('#response').append(html);
      loadmore_params.current_page++;
    }
  });
});

function getSelectedCategories() { return $('.filter-category:checked').map(function () { return $(this).val(); }).get(); } $('.load-more').on('click', function () { $.ajax({ url: loadmore_params.ajaxurl, type: 'POST', data: { action: 'load_more_posts', page: loadmore_params.current_page, categories: getSelectedCategories() }, success: function (html) { $('#response').append(html); loadmore_params.current_page++; } }); });

В PHP:

$categories = isset($_POST['categories']) ? array_map('absint', (array) $_POST['categories']) : [];
 
$args = [
    'post_type' => 'post',
    'paged' => max(1, (int) $_POST['page']),
];
 
if ($categories) {
    $args['tax_query'] = [
        [
            'taxonomy' => 'category',
            'field' => 'term_id',
            'terms' => $categories,
        ],
    ];
}

$categories = isset($_POST['categories']) ? array_map('absint', (array) $_POST['categories']) : []; $args = [ 'post_type' => 'post', 'paged' => max(1, (int) $_POST['page']), ]; if ($categories) { $args['tax_query'] = [ [ 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => $categories, ], ]; }

Когда фильтр меняется, сбрасывайте страницу пагинации на 1 и очищайте контейнер результатов. Иначе «Показать ещё» может подгружать вторую страницу уже от старого фильтра. Также добавьте nonce, чтобы AJAX-обработчик не принимал произвольные запросы без проверки.

Дополнительно храните выбранные фильтры в data-атрибутах кнопки или в отдельном объекте состояния. Когда пользователь меняет фильтр, обновляйте это состояние и сбрасывайте счётчик страницы. Иначе классическая ошибка такая: первый AJAX-запрос идёт с новыми категориями, а «Показать ещё» продолжает брать старые параметры, переданные при первой загрузке страницы.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно