usuario2115227
Tengo un filtro AJAX bien definido, en dos partes, una para cargar más botón y otra para una selección de filtros desplegables. Ambos recargan una lista de propiedades en el front-end en AJAX y trabajan juntos al unísono (por ejemplo, si selecciono Precio mínimo, Precio máximo y número de camas en los menús desplegables, la lista se actualiza y el botón Cargar más funciona como debería) .
Los mismos filtros también funcionan con parámetros de URL. Entonces, por ejemplo, si la URL fuera:
mydomain.com/?min_price=100000&max_price=5000000&beds=3&page=3
Se filtraría por esos parámetros. Incluso muestra 3 páginas de propiedades como debería. Esto funciona muy bien, incluso en la carga inicial. Sin embargo, no funciona con la paginación, SI la URL se carga directamente. Si ingreso la URL anterior directamente en el navegador y la cargo, los resultados iniciales son correctos, pero al hacer clic en el botón Cargar más, cambia de página = 3 a página = 4 (correcto) pero agrega la segunda página de propiedades completa sin filtrar , y continúa haciéndolo, en lugar de continuar con la paginación filtrada.
¿Qué estoy haciendo mal?
Aquí está mi código (¡lo siento, es mucho!)
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;
});
});
Funciones.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();
}
y el 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> -->
Este bloque de código se ejecuta cuando #prop_loadmore
se hace clic:
var params = new URLSearchParams(location.search);
params.set('page', prop_loadmore_params.current_page);
window.history.replaceState({}, "", decodeURIComponent(`${location.pathname}?${params}`));
Tu estas usando prop_loadmore_params
que incrementa su página actual cuando se hace clic en el botón, pero no parece tener ninguna referencia a price_min
o price_max
deberías ajustar $('#prop_loadmore').click(function(){...})
para incluir algo como:
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}`));
y luego en $('#filter').change(function(){})
asegúrese de agregar los valores filtrados al prop_loadmore_params
objeto.
¡Déjame saber como va!
Usted envía CORREO con AJAX pero verificas en PHP con $_GET[‘page’]
if (!empty($_GET['page'])) {
$the_page = $_GET['page'];
}
Puedes usar $_SOLICITUD
Al final, lo resolví yo mismo. La forma en que lo hice fue pasando los parámetros de URL a variables antes de que se ejecutara loadmore AJAX, algo así
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");
Esto hizo que la SOLICITUD funcionara en la llamada ajax al hacer clic en el botón cargar más
por favor proporcione la subcontratación de SOURCE compilado para que pueda ver prop_loadmore_params objeto
– Abdelrahman Gobarah
31 de enero de 2020 a las 10:50
Lo siento, no entiendo lo que eso significa?
– usuario2115227
31 de enero de 2020 a las 12:04
URL: prop_loadmore_params.ajaxurl, esta línea de la función Ajax 3ª línea Necesito ver prop_loadmore_params objeto con valores
– Abdelrahman Gobarah
31 de enero de 2020 a las 12:32
¿Esta página está cargada en línea? ¿puedes proporcionarme el enlace?
– Abdelrahman Gobarah
31 de enero de 2020 a las 12:38
@user2115227 ¿puede mostrarnos el valor de
prop_loadmore_params
. Solo usa$(document).ready(function () {console.log(prop_loadmore_params) });
– Aabir Hussein
5 de febrero de 2020 a las 16:46