Trong bài này chúng ta sẽ phân trang bằng Ajax sử dụng paginate_links – là 1 hàm có sẵn trong WordPress. Việc sử dụng hàm paginate_links có sẵn thì chúng ta không cần lo lắng về phân trang khi viết query post nữa rồi.
Vấn đề và cách giải quyết
- Tại sao cần phân trang bằng Ajax nhỉ?
- Hàm paginate_links có khác biệt gì khi sử dụng với Ajax?
Chúng ta có 1 trang chủ gồm nhất nhiều nội dung (Slider, giới thiệu, đối tác, testimonial, tin tức …) nhưng mục tin tức lại nằm ở cuối cùng của trang chủ. Trong khi đó lại có phân trang. Vậy bây giờ chẳng lẽ mỗi lần kích phân trang lại load lại trang và nhảy lên đầu tiên ah? => Sử dụng Ajax tại mục tin tức.
Ví dụ khác như trên trang chủ gồm nhiều mục tin tức và mỗi mục tin tức lại có phân trang => trong trường hợp này cần sử dụng Ajax
Để duy trì blog nên mình có làm aff cho 1 số bên hosting. Nhưng dù aff mình cũng chọn 1 số nhà cung cấp uy tín về chất lượng và support nên các bạn cứ yên tâm nhé.
Nếu có mua hosting mà có trong list dưới đây các bạn click vào link trước khi mua để ủng hộ mình nhé. Mình cảm ơn nhiều
- Azdigi: Giá rẻ thì dùng gói Pro Gold Hosting còn chất lượng hơn thì em khuyên dùng Business Hosting. Có điều kiện thì lên VPS nhé
- Tino hosting
- iNet
- Nước ngoài thì Vultr
Mặc định link phân trang của hàm paginate_links sẽ có dạng: link_page_hiện_tại/page/2 nhưng khi load bằng Ajax link phân trang sẽ có dạng /wp-admin/admin-ajax.php/?paged=2 . Link đó là sai … Chúng ta chỉ cần để base dạng như sau là được.
'base' => trailingslashit( home_url() ) . "{$wp_rewrite->pagination_base}/%#%/",
Ví dụ thực tế về phân trang bằng Ajax sử dụng paginate_links
Hình ảnh cho ví dụ sau khi hoàn thành. Demo trực tiếp tại đây
Trước tiên là đoạn php Query để lấy 4 tin tức mới nhất kèm theo phân trang. Đoạn code này để vào chỗ cần hiển thị trên trang chủ.
<?php $news = new WP_Query(array( 'post_type' => 'post', 'posts_per_page' => 4 )); if($news->have_posts()): $max_post_count = $news->post_count; ?> <div class="home_tintuc"> <div class="container"> <div class="home_news_main"> <div class="home_news_wrap"> <?php $stt = 1; while ($news->have_posts()):$news->the_post();?> <?php if($stt == 1):?><div class="home_news_col1"><?php endif;?> <?php if($stt == 2):?><div class="home_news_col2"><?php endif;?> <?php $thumb = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'thumbnail' ); $urlThumb = $thumb['0']; ?> <div class="tintuc_box <?php if(has_post_thumbnail()):?>has_post_thumbnail<?php endif;?>"> <?php if(has_post_thumbnail()):?> <div class="tintuc_box_thumb"><a href="<?php the_permalink();?>" title="<?php the_title()?>" style="background: url(<?php echo $urlThumb;?>) no-repeat center center"><?php the_post_thumbnail('thumbnail');?></a></div> <?php endif;?> <div class="tintuc_box_infor"> <h3><a href="<?php the_permalink();?>" title="<?php the_title()?>"><?php the_title();?></a></h3> <div class="news_infor_cat"><?php the_category(', ');?></div> <div class="news_date"><?php echo get_the_date();?></div> <div class="news_excerpt"><?php the_excerpt();?></div> <a href="<?php echo get_the_permalink();?>" title="<?php the_title();?>" rel="nofollow" class="news_readmore"><?php _e('Xem thêm >>','devvn')?></a> </div> </div> <?php if($stt == 1 || $stt == $max_post_count):?></div><?php endif;?> <?php $stt++; endwhile;?> </div> <?php devvn_corenavi_ajax($news);?> </div> </div> </div> <?php endif; wp_reset_query();//End news?>
Còn đây là hàm phân trang. Sử dụng paginate_links – hàm mặc định của WordPress. Copy đoạn code sau vào file functions.php của theme đang sử dụng
function devvn_corenavi_ajax($custom_query = null, $paged = 1) { global $wp_query, $wp_rewrite; if($custom_query) $main_query = $custom_query; else $main_query = $wp_query; $big = 999999999; $total = isset($main_query->max_num_pages)?$main_query->max_num_pages:''; if($total > 1) echo '<div class="paginate_links">'; echo paginate_links( array( 'base' => trailingslashit( home_url() ) . "{$wp_rewrite->pagination_base}/%#%/", 'format' => '?paged=%#%', 'current' => max( 1, $paged ), 'total' => $total, 'mid_size' => '5', 'prev_text' => __('<<','devvn'), 'next_text' => __('>>','devvn'), ) ); if($total > 1) echo '</div>'; }
Tiếp theo là hàm xử lý Ajax thông qua admin-ajax.php. Copy đoạn code sau vào file functions.php của theme đang sử dụng (Để ngay sau đoạn code phân trang phía trên). Trong đoạn php này có hàm check nonce. nếu bạn không cần validate nonce (liên quan tới bảo mật) thì bỏ nó đi cũng được (từ dòng 5 – 7)
//Ajax load post add_action( 'wp_ajax_ajax_load_post', 'ajax_load_post_func' ); add_action( 'wp_ajax_nopriv_ajax_load_post', 'ajax_load_post_func' ); function ajax_load_post_func() { if ( !wp_verify_nonce( $_REQUEST['nonce'], "ajax_load_post_nonce")) { wp_send_json_error('None?'); } $paged = isset($_POST['ajax_paged'])?intval($_POST['ajax_paged']):''; if($paged <= 0 || !$paged || !is_numeric($paged)) wp_send_json_error('Paged?'); $news = new WP_Query(array( 'post_type' => 'post', 'posts_per_page' => 4, 'paged' => $paged )); if($news->have_posts()): ob_start(); $max_post_count = $news->post_count; ?> <div class="home_news_wrap"> <?php $stt = 1; while ($news->have_posts()):$news->the_post();?> <?php if($stt == 1):?><div class="home_news_col1"><?php endif;?> <?php if($stt == 2):?><div class="home_news_col2"><?php endif;?> <?php $thumb = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'thumbnail' ); $urlThumb = $thumb['0']; ?> <div class="tintuc_box <?php if(has_post_thumbnail()):?>has_post_thumbnail<?php endif;?>"> <?php if(has_post_thumbnail()):?> <div class="tintuc_box_thumb"><a href="<?php the_permalink();?>" title="<?php the_title()?>" style="background: url(<?php echo $urlThumb;?>) no-repeat center center"><?php the_post_thumbnail('thumbnail');?></a></div> <?php endif;?> <div class="tintuc_box_infor"> <h3><a href="<?php the_permalink();?>" title="<?php the_title()?>"><?php the_title();?></a></h3> <div class="news_infor_cat"><?php the_category(', ');?></div> <div class="news_date"><?php echo get_the_date();?></div> <div class="news_excerpt"><?php the_excerpt();?></div> <a href="<?php echo get_the_permalink();?>" title="<?php the_title();?>" rel="nofollow" class="news_readmore"><?php _e('Xem thêm >>','devvn')?></a> </div> </div> <?php if($stt == 1 || $stt == $max_post_count):?></div><?php endif;?> <?php $stt++; endwhile; wp_reset_query();?> </div> <?php devvn_corenavi_ajax($news,$paged);?> <?php $content = ob_get_clean();?> <?php else:?> <?php wp_send_json_error('No post?');?> <?php endif; //End news wp_send_json_success($content); die(); }
Tiếp theo là đoạn script để thực hiện việc load ajax. Hãy tạo 1 file ajax-loadpost.js với nội dung bên dưới và để trong folder js của theme. Trong đoạn script dưới đây có thông sốdevvn_array.load_post_nonce bạn có thể xóa nếu không dùng tới nonce (dòng 16)
(function($) { $(document).ready(function() { $(".home_news_main").on('click','.paginate_links a',function(e){ e.preventDefault(); var hrefThis = $(this).attr('href'); var paged = hrefThis.match(/\/\d+\//)[0]; paged = paged.match(/\d+/)[0]; if(!paged) paged = 1; $.ajax({ type : "post", dataType : "json", url : devvn_array.admin_ajax, data : { action: "ajax_load_post", ajax_paged : paged, nonce: devvn_array.load_post_nonce }, context: this, beforeSend: function(){ $('.home_news_main').addClass('active'); }, success: function(response) { if(response.success) { $(response.data).addClass('holder'); $(".home_news_main").empty(); $(".home_news_main").append($(response.data)); } $('.home_news_main').removeClass('active'); } }); }); }); })(jQuery);
Tiếp theo là đoạn code php sử dụng wp_enqueue_script để theme file ajax-loadpost.js bên trên vào theme. Xem thêm cách thêm script vào theme WordPress 1 cách chuẩn nhất.
Hãy copy đoạn code sau vào file functions.php của theme đang sử dụng
add_action( 'wp_enqueue_scripts', 'devvn_enqueue_UseAjaxInWp' ); function devvn_enqueue_UseAjaxInWp(){ wp_enqueue_script( 'devvn-ajaxload', esc_url( trailingslashit( get_template_directory_uri() ) . 'js/ajax-loadpost.js' ), array( 'jquery' ), '1.0', true ); $php_array = array( 'admin_ajax' => admin_url( 'admin-ajax.php'), 'load_post_nonce' => wp_create_nonce('ajax_load_post_nonce'), ); wp_localize_script( 'devvn-ajaxload', 'devvn_array', $php_array ); }
Cuối cùng là đoạn style làm đẹp cho đoạn code trên 😀
.home_news_main { position: relative; } .home_news_main:before { display: inline-block; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); -webkit-transform: translate(-50%,-50%); font-size: 2em; visibility: hidden; opacity: 0; width: 64px; height: 64px; background: url(../images/Preloader_2.gif) no-repeat center; z-index: 2; content: ''; } .home_news_main.active:before, .home_news_main.active:after { opacity: 1; visibility: visible; } .home_news_wrap { margin: 10px 0; } .home_news_col1 { width: 63.55%; float: left; } .tintuc_box { overflow: hidden; margin: 0 0 10px; } .home_news_col1 .tintuc_box { box-shadow: 0 1px 6px 0px rgba(0,0,0,0.3); } .tintuc_box_thumb { width: 127px; float: left; } .home_news_col1 .tintuc_box_thumb { width: 60%; } .tintuc_box_thumb a { display: block; height: 0; padding-top: 100%; width: 100%; background-size: cover !important; -moz-background-size: cover !important; -webkit-background-size: cover !important; } .tintuc_box_thumb img { opacity: 0; visibility: hidden; display: inline-block; opacity: 0; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=100); -moz-opacity: 0; -khtml-opacity: 0; position: absolute; top: 0; left: 0; } .tintuc_box_infor { padding: 0 0 0 20px; color: #6d6e71; } .has_post_thumbnail .tintuc_box_infor { margin-left: 127px; } .home_news_col1 .tintuc_box_infor { padding: 20px; } .home_news_wrap:after, .tintuc_box:after { content: ""; clear: both; display: table; } .tintuc_box_infor h3 { max-height: 39px; overflow: hidden; } .home_news_col1 .tintuc_box_infor h3 { margin: 0 0 5px; } .tintuc_box_infor h3 a { font-size: 16px; color: #6d6e71; line-height: 20px; display: block; } .home_news_col1 .news_infor_cat { margin: 0 0 5px; } .news_infor_cat:before { content: ">>"; margin: 0 2px 0 0; } .news_infor_cat a { font-size: 12px; display: inline-block; color: #6d6e71; } .news_date { font-size: 12px; margin: 5px 0; display: block; } .news_date:before { content: "\f073"; display: inline-block; font: normal normal normal 12px/1 FontAwesome; font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; display: inline-block; margin: 0 5px 0 0; color: #f48120; font-size: 12px; position: relative; } .news_excerpt { margin: 0; max-height: 45px; overflow: hidden; text-align: justify; } .home_news_col1 .news_excerpt { margin: 0 0 30px; max-height: 211px; text-align: justify; } .tintuc_box_infor .news_readmore { color: #f48120; font-size: 16px; font-weight: 700; } .home_news_col2 { width: 33.18%; float: right; } /*Css phân trang*/ .paginate_links { text-align: left; color: #FF9B00; } .paginate_links .page-numbers { padding: 4px 10px; margin: 0 2px 5px 0; text-align: center; background: #e1e1e1; color: #6d6e71; text-decoration: none; display: inline-block; } .paginate_links .current, .paginate_links .page-numbers:hover { background: #f48120; color: #fff; }
Trong quá trình làm có bất kỳ thắc mắc gì hãy comment bên dưới bài viết. Mình sẽ cố gắng giải đáp 🙂
Tải bộ code trên tại đây
- Bình luận