Tôi có một bộ lọc AJAX được xác định rõ, gồm hai phần, một cho nút tải thêm và một cho bộ lọc thả xuống. Cả hai đều tải lại danh sách các thuộc tính ở giao diện người dùng trong AJAX và hoạt động cùng nhau (ví dụ: Nếu tôi chọn Giá tối thiểu, giá tối đa và số giường trong danh sách thả xuống, danh sách sẽ làm mới và nút tải thêm hoạt động như bình thường) .
Các bộ lọc tương tự cũng hoạt động với các tham số URL. Vì vậy, ví dụ: nếu URL là:
mydomain.com/?min_price=100000&max_price=5000000&beds=3&page=3
Nó sẽ lọc theo các tham số đó. Nó thậm chí còn hiển thị 3 trang giá trị tài sản như nó cần. Điều này hoạt động rất tốt, bao gồm cả trên tải ban đầu. Tuy nhiên, nó không hoạt động với phân trang, NẾU URL được tải trực tiếp. Nếu tôi nhập URL trên trực tiếp vào trình duyệt và tải, kết quả ban đầu là chính xác, nhưng khi nhấp vào nút Tải thêm, nó sẽ thay đổi trang = 3 thành trang = 4 (chính xác) nhưng nó sẽ thêm trang thứ hai của các thuộc tính chưa được lọc và tiếp tục làm như vậy - thay vì thực hiện phân trang được lọc.
Tôi đang làm gì sai?
Đây là mã của tôi (xin lỗi nó rất nhiều!)
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;
});
});
Hàm.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();
}
và 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> -->
prop_loadmore_params
. Chỉ cần sử dụng$(document).ready(function () {console.log(prop_loadmore_params) });