Faire fonctionner la pagination AJAX avec les paramètres de filtre URL (AJAX) lors de l'actualisation

9

J'ai un filtre AJAX bien défini, en deux parties, une pour un bouton de chargement plus et une pour une sélection de filtres déroulants. Les deux rechargent une liste de propriétés sur le front-end dans AJAX et fonctionnent ensemble à l'unisson (par exemple, si je sélectionne le prix Min, le prix Max et le nombre de lits dans les listes déroulantes, la liste s'actualise et le bouton Charger plus fonctionne comme il se doit) .

Les mêmes filtres fonctionnent également avec les paramètres d'URL. Ainsi, par exemple, si l'URL était:

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

Il filtrerait par ces paramètres. Il montre même 3 pages de propriétés comme il se doit. Cela fonctionne très bien, y compris lors de la charge initiale. Cependant, cela ne fonctionne pas avec la pagination, SI l'URL est chargée directement. Si j'entre l'URL ci-dessus directement dans le navigateur et que je charge, les résultats initiaux sont corrects, mais en cliquant sur le bouton Charger plus, cela change page = 3 en page = 4 (correct) mais il ajoute la deuxième page de propriétés complétée non filtrée , et continue de le faire - plutôt que de poursuivre la pagination filtrée.

Qu'est-ce que je fais mal?

Voici mon code (désolé c'est beaucoup!)

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();
}

et le 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
la source
veuillez nous fournir l'externalisation de la SOURCE compilée afin que je puisse voir l' objet prop_loadmore_params
Abdelrahman Gobarah
Désolé, je ne comprends pas ce que cela signifie?
user2115227
url: prop_loadmore_params.ajaxurl, cette ligne de la fonction Ajax 3ème ligne doit voir l' objet prop_loadmore_params avec des valeurs
Abdelrahman Gobarah
cette page est-elle téléchargée en ligne? pouvez-vous me fournir le lien?
Abdelrahman Gobarah
@ user2115227 pouvez-vous nous montrer la valeur de prop_loadmore_params. Il suffit d'utiliser$(document).ready(function () {console.log(prop_loadmore_params) });
Aabir Hussain

Réponses:

1

Ce bloc de code est exécuté lorsque l' #prop_loadmoreon clique sur:

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

Vous utilisez prop_loadmore_paramsqui incrémente sa page actuelle lorsque le bouton est cliqué, mais ne semble pas avoir de référence à price_minouprice_max

Vous devez vous ajuster $('#prop_loadmore').click(function(){...})pour inclure quelque chose comme:

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}`));

Et puis $('#filter').change(function(){})assurez-vous d'ajouter les valeurs filtrées à l' prop_loadmore_paramsobjet.

Faites-moi savoir comment ça se passe!

JobiWon9178
la source
0

Vous envoyez POST avec AJAX mais vous vérifiez en PHP avec $ _GET ['page']

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

Vous pouvez utiliser $ _REQUEST

Abdelrahman Gobarah
la source
0

En fin de compte, j'ai résolu cela moi-même. La façon dont je l'ai fait était de passer les paramètres d'URL dans des variables avant le lancement de loadmore AJAX, quelque chose dans ce sens

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");

Cela a ensuite fait fonctionner la DEMANDE sur l'appel ajax en cliquant sur le bouton charger plus

user2115227
la source