Заставьте AJAX Pagination работать с (AJAX) параметрами фильтра URL при обновлении

9

У меня есть четко определенный фильтр AJAX, состоящий из двух частей: одна для кнопки «Загрузить еще», а другая для выбора раскрывающихся фильтров. Обе перезагрузки списка свойств в интерфейсе в AJAX, и работают вместе в унисон (например, если я выбираю минимальную цену, максимальную цену и количество кроватей в раскрывающихся списках, список обновляется, и кнопка загрузки еще работает как надо) ,

Эти же фильтры также работают с параметрами URL. Так, например, если URL был:

mydomain.com/?min_price=100000&max_price=5000000&beds=3&page=3

Это будет фильтровать по этим параметрам. Он даже показывает свойства на 3 страницы, как и должно быть. Это прекрасно работает, в том числе и при начальной загрузке. Тем не менее, он не работает с нумерацией страниц, если URL загружен напрямую. Если я введу вышеуказанный URL-адрес непосредственно в браузер и загрузлю, начальные результаты верны, но при нажатии кнопки «Загрузить еще» он изменит страницу = 3 на страницу = 4 (правильно), но добавит вторую страницу свойств, заполненных без фильтрации. и продолжает это делать - вместо того, чтобы продолжать фильтрованную нумерацию страниц.

Что я делаю неправильно?

Вот мой код (извините, это много!)

JS:

jQuery(function($){


 // AJAX Stuff for filters + load more button

/*
 * Load More
 */
$('#prop_loadmore').click(function(){

    $.ajax({
        url : prop_loadmore_params.ajaxurl, 
        data : {
            'action': 'loadmorebutton',
            'query': prop_loadmore_params.posts, // loop parameters passed by wp_localize_script()
            'page' : prop_loadmore_params.current_page, // Get the current page

        },
        type : 'POST',
        beforeSend : function ( xhr ) {
            $('#prop_loadmore').text( 'Loading...' ); 
            $('#prop_loadmore').addClass( 'loading' );

        },
        success : function( posts ){
            if( posts ) {
                $('#prop_loadmore').removeClass( 'loading' );
                $('#prop_loadmore').text( 'More Listings' );
                $('#main_posts').append( posts ); 
            //    $(".price-txt").digits(); // Add the commas!
                localStorage.setItem("posts", posts);
                prop_loadmore_params.current_page++; // Increase current page by 1

                var params = new URLSearchParams(location.search);
                params.set('page', prop_loadmore_params.current_page);
                window.history.replaceState({}, "", decodeURIComponent(`${location.pathname}?${params}`));


                if ( prop_loadmore_params.current_page == prop_loadmore_params.max_page ) 
                    $('#prop_loadmore').hide(); // if last page, hide loadmore

            } else {
                $('#prop_loadmore').hide(); // if no properties, hide loadmore
            }
        }
    });
    return false;
});

/*
 * Filter
 */
$('#filter').change(function(){

    $.ajaxSetup({cache: false});

    $.ajax({
        url : prop_loadmore_params.ajaxurl,
        data : $('#filter').serialize(), 
        dataType : 'json',

        success : function( data ){

            // reset current page to 1 when filters on
            prop_loadmore_params.current_page = 1;

            prop_loadmore_params.posts = data.posts;

            // set max page
            prop_loadmore_params.max_page = data.max_page;

            found_posts = data.found_posts 

            //First pull out the empty strings

            var formData = $('#filter').serializeArray().filter(function (i) {
                if(i.value != 'prop_filters') {
                    return i.value;
                }
            });

            //Now push formData to URL
            window.history.pushState('', 'title', '?' + $.param(formData) + '&page=' + prop_loadmore_params.current_page);

            $('#main_posts').html(data.content);
            $('.listings-count').text( found_posts + ' Real Estate Listings for Sale' );


            if (found_posts > 9) {
                $('#prop_loadmore').show();
            }
             if ( prop_loadmore_params.current_page == prop_loadmore_params.max_page ) 
                    $('#prop_loadmore').hide(); // if last page, hide loadmore




            // If not enough posts for 2nd page, hide loadmore
            if ( data.max_page < 2 ) {
                $('#prop_loadmore').hide();
            } else {
                $('#prop_loadmore').show();
            }
        }
    });

    return false;

});

});

Functions.php:

add_action( 'wp_enqueue_scripts', 'properties_script_and_styles');

function properties_script_and_styles() {
global $wp_query;

wp_register_script( 'property_scripts', get_stylesheet_directory_uri() . '/assets/js/properties.js', array('jquery') );


$the_page = $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1;

if (!empty($_GET['page'])) {
    $the_page = $_GET['page'];
}

wp_localize_script( 'property_scripts', 'prop_loadmore_params', array(
    'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', 
    'posts' => $wp_query->query_vars,
    'current_page' => $the_page,
    'max_page' => $wp_query->max_num_pages,
    'found_posts' => $wp_query->found_posts,

) );

wp_enqueue_script( 'property_scripts' );
}

add_action('wp_ajax_loadmorebutton', 'prop_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmorebutton', 'prop_loadmore_ajax_handler');

function prop_loadmore_ajax_handler(){

$args = json_decode(  $_POST['query'] ); 
$args['paged'] = $_POST['page'] + 1; 
 if (!is_user_logged_in()) {
    $args['post_status'] = 'publish';
}
else {
    $args['post_status'] = array('publish', 'private');
}
query_posts( $args );

if( have_posts() ) :


    while( have_posts() ): the_post();

        get_template_part( 'template-parts/post/content', get_post_format() );

    endwhile;
endif;
die;
}


function prepare_property_filters(array $args): array {

/** Price Args**/

if (!empty($_REQUEST['price_min']) || !empty($_REQUEST['price_max'])) 
{
    $args['meta_query'] = ['relation'=>'AND'];
}

// If Both
if( !empty( $_REQUEST['price_min'] ) && !empty( $_REQUEST['price_max'] )) {
    $args['meta_query'][] = array(
        'key' => 'price',
        'value' => array( $_REQUEST['price_min'], 
$_REQUEST['price_max'] ),
        'type' => 'numeric',
        'compare' => 'between'
    );
} else {
    // if only min price
    if( !empty( $_REQUEST['price_min'] ) ) {
        $args['meta_query'][] = array(
            'key' => 'price',
            'value' => $_REQUEST['price_min'],
            'type' => 'numeric',
            'compare' => '>'
        );
    }
}

    // if only max price
    if( !empty( $_REQUEST['price_max'] ) ) {
        $args['meta_query'][] = array(
            'key' => 'price',
            'value' => $_REQUEST['price_max'],
            'type' => 'numeric',
            'compare' => '<'
        );
    }

//* 
// Bedrooms Arg
//*
    if( !empty( $_REQUEST['beds'] ) ) {
        $args['meta_query'][] = array(
            'key' => 'bedrooms',
            'value' => $_REQUEST['beds'],
            'type' => 'numeric',
            'compare' => '>='
        );
    }

//* 
// Property Type Arg
//*
    if( !empty( $_REQUEST['type'] ) ) {
        $args['meta_query'][] = array(
            'key' => 'property_type',
            'value' => $_REQUEST['type'],
            'compare' => 'IN'
        );
    }

return $args;
}


add_action('wp_ajax_prop_filters', 'property_filters'); 
add_action('wp_ajax_nopriv_prop_filters', 'property_filters');

function property_filters() {
//*
// Sort by Args
//*

    if( $_REQUEST['sort_by'] === 'price-desc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'DESC';
        $meta_key = 'price';
    }

    elseif( $_REQUEST['sort_by'] === 'price-asc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'ASC';
        $meta_key = 'price';
    }
    elseif( $_REQUEST['sort_by'] === 'bedrooms-desc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'DESC';
        $meta_key = 'bedrooms';
    }
    elseif( $_REQUEST["sort_by"] === 'bedrooms-asc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'ASC';
        $meta_key = 'bedrooms';
    }
    else {
        $orderby = 'date'; 
        $order = 'DESC';
        $meta_key = '';
    }
$args = prepare_property_filters([
    'posts_per_page' => 9, 
    'post_status' => is_user_logged_in() ? ['publish', 'private'] : ['publish'],
    'paged' => $_POST['page'],
    'meta_key' => $meta_key,
    'orderby' => $orderby,
    'order' => $order
]);
query_posts( $args );

    global $wp_query;

    if( have_posts() ) :

        ob_start();

        while( have_posts() ): the_post();

            get_template_part( 'template-parts/post/content', get_post_format() );

        endwhile;

        $posts_html = ob_get_contents(); 
        ob_end_clean(); 
    else:
        $posts_html = '<p>Nothing found for your criteria.</p>';
    endif;

    echo json_encode( array(
        'posts' => json_encode( $wp_query->query_vars ),
        'max_page' => $wp_query->max_num_pages,
        'found_posts' => $wp_query->found_posts,
        'content' => $posts_html,
    ) );

    die();
}

и HTML:

<input id="filter_toggle"  type="checkbox">
<?php //We need to save the varaibles in arrays, so we can then check them against the URL and populate the dropdowns

$price_min = [
'' => 'Any Price',
'100000' => '$100,000',
'150000' => '$150,000',
'200000' => '$200,000',
'250000' => '$250,000',
//etc
];

$price_max = [
'' => 'Any Price',
'100000' => '$100,000',
'150000' => '$150,000',
'200000' => '$200,000',
'250000' => '$250,000',
//etc
];

$beds = [
'' => 'All Beds',
'1' => '1+',
'2' => '2+',
'3' => '3+',
'4' => '4+',
'5' => '5+'
];

$property_type = [
'' => 'All Property Types',
'single-family-home' => 'Single Family Home',
'condo' => 'Condo',
'land' => 'Land',
'townhouse' => 'Townhouse'
];

$sort_by = [
'newest' => 'Sort by Newest',
'price-desc' => 'Sort by Price (High to Low)',
'price-asc' => 'Sort by Price (Low to High)',
'bedrooms-desc' => 'Sort by Beds (Most to Least)',
'bedrooms-asc' => 'Sort by Beds (Least to Most)'
];
?>

<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
<div class="filters_options">

  <select name="price_min" class="min_max_select">
    <option disabled="disabled" selected="" value="">Minimum Price</option>
    <?php foreach ($price_min as $key => $value) {
         $selected = '';
         if ($_GET['price_min'] == $key) {
             $selected = ' selected="selected"';
         }
         printf(
             '<option value="%s"%s>%s</option>',
             $key,
             $selected,
             $value
         );
     } ?>
  </select>

  <select name="price_max" class="min_max_select">
    <option disabled="disabled" selected="selected" value="">Maximum Price</option>
    <?php foreach ($price_max as $key => $value) {
         $selected = '';
         if ($_GET['price_max'] == $key) {
             $selected = ' selected="selected"';
         }
         printf(
             '<option value="%s"%s>%s</option>',
             $key,
             $selected,
             $value
         );
     } ?>
  </select>

  <select name="beds" class="select_beds">
    <option disabled="disabled" selected="selected" value="">Bedrooms</option>
    <?php foreach ($beds as $key => $value) {
         $selected = '';
         if ($_GET['beds'] == $key) {
             $selected = ' selected="selected"';
         }
         printf(
             '<option value="%s"%s>%s</option>',
             $key,
             $selected,
             $value
         );
     } ?>
  </select>

  <!-- <select>
    <option disabled="disabled" selected="selected" value="">Bathrooms</option>
    <option value="">All Baths</option>
    <option value="1+">1+</option>
    <option value="1+">2+</option>
    <option value="1+">3+</option>
    <option value="1+">4+</option>
    <option value="1+">5+</option>
  </select> -->

  <select name="type" class="sort_by_property_type">
    <option disabled="disabled" selected="selected" value="">Property Type</option>
    <?php foreach ($property_type as $key => $value) {
         $selected = '';
         if ($_GET['type'] == $key) {
             $selected = ' selected="selected"';
         }
         printf(
             '<option value="%s"%s>%s</option>',
             $key,
             $selected,
             $value
         );
     } ?>
  </select>

  <!-- <select>
    <option disabled="disabled" selected="selected" value="">Property View</option>
    <option value="">All Property Views</option>
    <option value="Golf View">Golf View</option>
    <option value="Ocean View">Ocean View</option>
    <option value="Ocean Front">Ocean Front</option>
  </select> -->

  <select name="sort_by" class="sort_by_dropdown">
    <?php
     foreach ($sort_by as $key => $value) {
         $selected = '';
         if ($_GET['sort_by'] == $key) {
             $selected = ' selected="selected"';
         }
         printf(
             '<option value="%s"%s>%s</option>',
             $key,
             $selected,
             $value
         );
     }
     ?>
  </select>

<input type="hidden" name="action" value="prop_filters" />
</div>

 <span class="reset_btn reset">reset</span>
<label class="done_btn" for="filter_toggle">Done</label>
</form> 
</div>

<ul id="main_posts" class="item-listings">
<?php 

//*
// Sort by Args
//*

    if( $_GET['sort_by'] === 'price-desc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'DESC';
        $meta_key = 'price';
    }

    elseif( $_GET['sort_by'] === 'price-asc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'ASC';
        $meta_key = 'price';
    }
    elseif( $_GET['sort_by'] === 'bedrooms-desc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'DESC';
        $meta_key = 'bedrooms';
    }
    elseif( $_GET["sort_by"] === 'bedrooms-asc' ) {
        $orderby = 'meta_value_num'; 
        $order = 'ASC';
        $meta_key = 'bedrooms';
    }
    else {
        $orderby = 'date'; 
        $order = 'DESC';
        $meta_key = '';
    }

    $per_page = 9;

    if(!empty( $_GET['page'])) {
        $per_page = $_GET['page'] * 9;
    }

// Build the inital Loop
$args = prepare_property_filters([
    'posts_per_page' => $per_page,
    'paged' => $_POST['page'],
    'meta_key' => $meta_key,
    'orderby' => $orderby,
    'order' => $order
]);

query_posts($args);

if( have_posts() ) :

    while( have_posts() ): the_post();

        get_template_part( 'template-parts/post/content', get_post_format() );

        $count_posts = $wp_query->found_posts; 

    endwhile;
endif;

?>
</ul>


<?php if (  $wp_query->max_num_pages > 1 ) :
    echo '<div id="prop_loadmore">More Listings</div>';
endif;?>

<span class="listings-count"><?php echo $count_posts;?> Real Estate Listings for Sale</span>
<!-- <span class="reset">reset</span> -->
user2115227
источник
пожалуйста, предоставьте нам аутсорсинг скомпилированного источника, чтобы я мог видеть объект prop_loadmore_params
Абдельрахман Гобара
Извините, я не понимаю, что это значит?
user2115227
url: prop_loadmore_params.ajaxurl, эту строку из 3-й строки функции Ajax нужно увидеть prop_loadmore_params объекта со значениями
Abdelrahman Gobarah
эта страница загружена онлайн? Можете ли вы предоставить мне ссылку?
Абдельрахман Гобара
@ user2115227 Можете ли вы показать нам значение prop_loadmore_params . Просто используйте$(document).ready(function () {console.log(prop_loadmore_params) });
Aabir Hussain

Ответы:

1

Этот блок кода выполняется при #prop_loadmoreнажатии:

var params = new URLSearchParams(location.search);
params.set('page', prop_loadmore_params.current_page);
window.history.replaceState({}, "", decodeURIComponent(`${location.pathname}?${params}`));

Вы используете, prop_loadmore_paramsкоторый увеличивает текущую страницу, когда кнопка нажата, но не имеет ссылки на price_minилиprice_max

Вы должны настроить $('#prop_loadmore').click(function(){...})что-то вроде:

var params = new URLSearchParams(location.search);

params.set('page', prop_loadmore_params.current_page);

//Add All Additional Parameters in this way
if (prop_loadmore_params.price_min){
     params.set('price_min', prop_loadmore_params.price_min);
}
if (prop_loadmore_params.price_max){
     params.set('price_max', prop_loadmore_params.price_max);
}
// ...

window.history.replaceState({}, "", decodeURIComponent(`${location.pathname}?${params}`));

И затем $('#filter').change(function(){})убедитесь, что вы добавляете отфильтрованные значения к prop_loadmore_paramsобъекту.

Дайте мне знать, как это происходит!

JobiWon9178
источник
0

Вы отправляете POST с AJAX, но проверяете в PHP с помощью $ _GET ['page']

if (!empty($_GET['page'])) {
    $the_page = $_GET['page'];
}

Вы можете использовать $ _REQUEST

Абдельрахман Гобара
источник
0

В конце концов, я решил это сам. Я сделал это, передав параметры URL в переменные до того, как AJAX-модуль loadmore запустился, что-то вроде этого

var url_string = window.location;
var price_min = (new URL(url_string)).searchParams.get("price_min");
var price_max = (new URL(url_string)).searchParams.get("price_max");
var bedrooms = (new URL(url_string)).searchParams.get("beds");
var property_type = (new URL(url_string)).searchParams.get("type");
var sort_by = (new URL(url_string)).searchParams.get("sort_by");
var the_page = (new URL(url_string)).searchParams.get("page");

Это затем заставило REQUEST работать при вызове ajax по нажатию кнопки «загрузить больше».

user2115227
источник