Load More Posts Ajax Button in WordPress
UPDATE 24.04.2016.
I've created tutorial on my page https://madebydenis.com/ajax-load-posts-on-wordpress/ about implementing this on Twenty Sixteen theme, so feel free to check it out :)
EDIT
I've tested this on Twenty Fifteen and it's working, so it should be working for you.
In index.php (assuming that you want to show the posts on the main page, but this should work even if you put it in a page template) I put:
<div id="ajax-posts" class="row">
<?php
$postsPerPage = 3;
$args = array(
'post_type' => 'post',
'posts_per_page' => $postsPerPage,
'cat' => 8
);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
?>
<div class="small-12 large-4 columns">
<h1><?php the_title(); ?></h1>
<p><?php the_content(); ?></p>
</div>
<?php
endwhile;
wp_reset_postdata();
?>
</div>
<div id="more_posts">Load More</div>
This will output 3 posts from category 8 (I had posts in that category, so I used it, you can use whatever you want to). You can even query the category you're in with
$cat_id = get_query_var('cat');
This will give you the category id to use in your query. You could put this in your loader (load more div), and pull with jQuery like
<div id="more_posts" data-category="<?php echo $cat_id; ?>">>Load More</div>
And pull the category with
var cat = $('#more_posts').data('category');
But for now, you can leave this out.
Next in functions.php I added
wp_localize_script( 'twentyfifteen-script', 'ajax_posts', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'noposts' => __('No older posts found', 'twentyfifteen'),
));
Right after the existing wp_localize_script
. This will load WordPress own admin-ajax.php so that we can use it when we call it in our ajax call.
At the end of the functions.php file I added the function that will load your posts:
function more_post_ajax(){
$ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 3;
$page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
header("Content-Type: text/html");
$args = array(
'suppress_filters' => true,
'post_type' => 'post',
'posts_per_page' => $ppp,
'cat' => 8,
'paged' => $page,
);
$loop = new WP_Query($args);
$out = '';
if ($loop -> have_posts()) : while ($loop -> have_posts()) : $loop -> the_post();
$out .= '<div class="small-12 large-4 columns">
<h1>'.get_the_title().'</h1>
<p>'.get_the_content().'</p>
</div>';
endwhile;
endif;
wp_reset_postdata();
die($out);
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
Here I've added paged key in the array, so that the loop can keep track on what page you are when you load your posts.
If you've added your category in the loader, you'd add:
$cat = (isset($_POST['cat'])) ? $_POST['cat'] : '';
And instead of 8, you'd put $cat
. This will be in the $_POST
array, and you'll be able to use it in ajax.
Last part is the ajax itself. In functions.js I put inside the $(document).ready();
enviroment
var ppp = 3; // Post per page
var cat = 8;
var pageNumber = 1;
function load_posts(){
pageNumber++;
var str = '&cat=' + cat + '&pageNumber=' + pageNumber + '&ppp=' + ppp + '&action=more_post_ajax';
$.ajax({
type: "POST",
dataType: "html",
url: ajax_posts.ajaxurl,
data: str,
success: function(data){
var $data = $(data);
if($data.length){
$("#ajax-posts").append($data);
$("#more_posts").attr("disabled",false);
} else{
$("#more_posts").attr("disabled",true);
}
},
error : function(jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
return false;
}
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
load_posts();
});
Saved it, tested it, and it works :)
Images as proof (don't mind the shoddy styling, it was done quickly). Also post content is gibberish xD
UPDATE
For 'infinite load' instead on click event on the button (just make it invisible, with visibility: hidden;
) you can try with
$(window).on('scroll', function () {
if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
load_posts();
}
});
This should run the load_posts()
function when you're 100px from the bottom of the page. In the case of the tutorial on my site you can add a check to see if the posts are loading (to prevent firing of the ajax twice), and you can fire it when the scroll reaches the top of the footer
$(window).on('scroll', function(){
if($('body').scrollTop()+$(window).height() > $('footer').offset().top){
if(!($loader.hasClass('post_loading_loader') || $loader.hasClass('post_no_more_posts'))){
load_posts();
}
}
});
Now the only drawback in these cases is that you could never scroll to the value of $(document).height() - 100
or $('footer').offset().top
for some reason. If that should happen, just increase the number where the scroll goes to.
You can easily check it by putting console.log
s in your code and see in the inspector what they throw out
$(window).on('scroll', function () {
console.log($(window).scrollTop() + $(window).height());
console.log($(document).height() - 100);
if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
load_posts();
}
});
And just adjust accordingly ;)
Hope this helps :) If you have any questions just ask.
Load More Custom Posts On Click Ajax WordPress
There is a good amount here to fix.
Your Ajax is syntax is off a bit. Also, you can specify posts per page for the return with PHP, so you don't need to send that, you can keep your page attribute on the frontend.
$("#more_posts").on("click", function(e) {
$.ajax({
// use the ajax object url
url: ajax_object.ajax_url,
data: {
action: "more_post_ajax", // add your action to the data object
offset: page * 4 // page # x your default posts per page
},
success: function(data) {
// add the posts to the container and add to your page count
page++;
$('.projects').append(data);
},
error: function(data) {
// test to see what you get back on error
console.log(data);
}
});
});
For your initial PHP function, you should only specify the amount of posts you want to show at first. If you use -1 it will just show all posts at the start, which you don't want. You also don't need to use the paged parameter. You only need offsets.
<?php
$args = array(
'post_type' => 'project',
'status' => 'publish',
'order' => 'ASC',
'posts_per_page' => 4,
);
$posts = new WP_Query($args);
?>
<div class="projects">
<?php
while ($posts->have_posts()) {
$posts->the_post(); ?>
<div class="project">
<?php the_title(); ?>
</div>
<?php
wp_reset_postdata();
}; ?>
</div>
For your more posts function, you only need to specify an offset, and can add your additional posts right in that function.
function more_post_ajax(){
$offset = $_POST["offset"];
$args = array(
'post_type' => 'project',
'status' => 'publish',
'posts_per_page' => 4,
'order' => 'ASC',
'offset' => $offset,
);
$post = new WP_Query($args);
while ($post->have_posts()) { $post->the_post();
<div class="project">the_title();</div>
}
wp_reset_postdata();
die(); // use die instead of exit
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
I have not tested this, but this should get you closer to a working set.
Load more posts in the same category - WordPress + Ajax + Timber
To be honest, it's difficult to understand you, but it seems to me that your problem is that you are pointing all the time to a global post
function get_news() {
global $post;
You need to explicitly request the category what does this mean, I will explain
You need to transfer id categories to the server, and not use global $post.
The algorithm is as follows:
1) return the category id to the button on the client
<button data-cid="{category_id}">Load more posts</button>
or somewhere in the parent element of the category
<div class="category" data-cid="<?php print $category_id; ?>">
<!-- 10 posts -->
<article class="post">...</article>
....
<button>Load more posts</button>
</div>
2) After clicking on the button, get this СID (category id) and send it to the server
function load_more_news() {
var page = 1;
$(document).on('click', '#load-more-news', function(e) {
let $el = $(this); // of e.currentTarget;
e.preventDefault();
page++;
$.ajax({
type: 'POST',
url: '/wp-admin/admin-ajax.php',
dataType: 'html',
data: {
'action': 'get_news',
'get_page': page,
'cid': $el.data('cid') // CID or $el.parents('[data-cid]').data('cid');
},
success: function(data) {
if ($('<div></div>').html(data).find('.archive__item.ended').size() > 0) $('#load-more-news').parents('.cta').remove();
else $('#load-more-news').parents('.cta').show();
$('#archive__list').append(data);
},
error: function(data) {
console.log(data);
}
});
});
}
3) use this on server instead of global post
'category__in' => array($_POST['cid'])
Addition:
What means: when I click on the button "Load more posts". No post are display. ?
- What is returned from the server?
- Check what you get with ::get_posts()?
- Why don't you just use get_posts of native wordpress api function ?
Check and debug all data that comes to the server and returns
Organize your code:
1.) send ajax url to the client
wp_register_script('your-script', PLUG_URL.'your-script.js', array('jquery'), filemtime( PLUG_DIR.'your-script.js' ), true);
wp_localize_script('your-script', 'glb',
array(
'ajax_url' => admin_url('admin-ajax.php')
)
);
and use it and use this instead of hardcore with $.post function of jquery (recommended)
let payload = {
page: 2
}
$.post(glb.ajax_url, {action: 'get_news', data: payload, function(e) {
....
});
2.) Check what comes to the server
function get_news() {
wp_send_json($_POST['data']);
}
$.post(glb.ajax_url, {action: 'get_news', data: payload, function(e) {
console.log(e); // {page: 2}
});
function get_news() {
if(!isset($_POST['data'])) {
wp_send_json_error();
}
$data = $_POST['data'];
$posts = get_posts( array(
'numberposts' => 10,
'post_status' => 'publish',
'category__in' => [$category],
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'post',
'paged' => $data['page']
));
wp_send_json($posts);
}
$.post(glb.ajax_url, {action: 'get_news', data: payload, function(e) {
console.log(e); // ???
});
Make checks, return data and look for where you have a "hole"
Load More Posts Ajax Button in Wordpress - fix
instead
'&ppp' + ppp
do
'&ppp=' + ppp
Related Topics
Difference Between Relative Path and Absolute Path in JavaScript
Are HTML Comments Inside Script Tags a Best Practice
Double Quote in JavaScript String
Use Html5 to Resize an Image Before Upload
Avoid Dropdown Menu Close on Click Inside
Launch Bootstrap Modal on Page Load
JavaScript; Communication Between Tabs/Windows With Same Origin
In Html5, Is the Localstorage Object Isolated Per Page/Domain
Change Link Color of the Current Page With Css
Populate One Dropdown Based on Selection in Another
How to Make Ng-Bind-Html Compile Angularjs Code
Why Does This Simple Jsfiddle Not Work
Difference Between ≪Script Src="Foo.Js"≫≪/Script≫ and ≪Script Src="Foo.Js"/≫
How to Get Current Formatted Date Dd/Mm/Yyyy in JavaScript and Append It to an Input
Export HTML Table Data to Excel Using JavaScript/Jquery Is Not Working Properly in Chrome Browser
How Is the Default Submit Button on an HTML Form Determined
Innertext VS Innerhtml VS Label VS Text VS Textcontent VS Outertext