Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

How to add Ajax paging to widget? WordPress

  • SOLVED

I created a custom widget plugin which displays my site's categories on the frontpage in a grid layout with a featured image and category description. I would like to add Ajax pagination so users can scroll through the available categories.

I already have the following code for displaying the widget content and the page navigation links:

<?php //Code for displaying the widget content
$title = apply_filters( 'widget_title', $instance['title'] );
// before and after widget arguments are defined by themes
echo $args['before_widget'];
if ( ! empty( $title ) )
echo '<h2>' . $title . '</h2>';
$catpage = get_query_var( 'page' ) ? get_query_var( 'page' ) : 1;
$catnum = 2; //number categories per page
$offset = ($catnum * $catpage) - 2; // same as above
$catsin = $instance['widget_categories'];
$child_categories = get_categories( array(
'orderby' => 'name',
'include' => $catsin,
'paged' => $catpage,
'offset' => $offset,
'number' => $catnum,
'hide_empty' => '0'
) );

if (!empty($child_categories)) { $count = 0;

echo '<div id="gridwrap" class="block1 block1_grid">';
echo '<div class="row">';

foreach ( $child_categories as $child ){ $count++;

include_once(plugin_dir_path( __FILE__ ) . '/../tpls/content-custom.php');

if ( $count % 2 == 0 ) {
echo '</div>';
echo '<div class="row">';
}
}
echo '</div>';
echo '</div>';
}
// Call to pagination function
custom_pagination($catpage, $catnum);
?>

Pagination function
function custom_pagination($catpage, $catnum) {
// Start of Pagination
$total_cats_query = get_categories('hide_empty=0&orderby=name');
$total_terms = count( $total_cats_query );
$pages = ceil($total_terms/$catnum);
$base_url = get_site_url();

// if there's more than one page
if( $pages > 1 ):
echo '<div class="ft-paginate">';
echo '<nav class="navigation pagination" role="navigation">';
echo '<h2 class="screen-reader-text">Posts navigation</h2>';
echo '<div id="navwrap" class="nav-links">';

// if we're not on the first page, print the previous-link
if ( $catpage > 1 ) {
$prevpage = $catpage - 1;
if ( $prevpage > 1 ) {
echo '<a class="prev page-numbers" href="' . $base_url . '/page/' . $prevpage . '"><i class="fa fa-angle-left"></i></a>';
} else {
echo '<a class="prev page-numbers" href="' . $base_url . '"><i class="fa fa-angle-left"></i></a>';
}
}

for ($pagecount=1; $pagecount <= $pages; $pagecount++):
//set class
$class = "page-numbers";
if ( $pagecount == $catpage ) {
$class .= " current";
}
if ( $pagecount == $catpage ) {
echo '&nbsp;<span class="' . $class . '"><span class="screen-reader-text">Page</span>' . $pagecount . '</span>';
}
else if ( $pagecount == 1 ) {
echo '&nbsp;<a class="' . $class . '" href="' . $base_url . '"><span class="screen-reader-text">Page</span>' . $pagecount . '</a>';
} else {
echo '&nbsp;<a class="' . $class . '" href="' . $base_url . '/page/' . $pagecount . '"><span class="screen-reader-text">Page</span>' . $pagecount . '</a>';
}
endfor;

// if there is one more page after the current, print the next-link
if ( $catpage < $pages ) {
$nextpage = $catpage + 1;
echo '&nbsp;<a class="next' . $class . '" href="' . $base_url . '/page/' . $nextpage . '"><i class="fa fa-angle-right"></i></a>';
}

echo '</div>';
echo '</nav>';
echo '</div>';

endif;
// End of Pagination
}


I found a [[LINK href="https://code.tutsplus.com/articles/getting-started-with-ajax-wordpress-pagination--wp-23099"]]tutorial[[/LINK]] on another site and think the code could probably be adapted to suit.

This is the script used in that tutorial which I've edited to include the relevant id selectors:

<script type="text/javascript" charset="utf-8">
jQuery(document).ready(function(){
jQuery('#navwrap a').live('click', function(e){
e.preventDefault();
var link = jQuery(this).attr('href');
jQuery('#ID').html('Loading...');
jQuery('#ID').load(link+' #gridwrap');

});

});
</script>

This is about as far as I can get on my own. I think the situation is complicated by the fact I'm displaying the widget on the frontpage and I'm dealing with categories rather than posts.

Answers (1)

2016-09-19

Rempty answers:

Hello
How many categories do you have?
If they are not to many categories, why not load all categories and with cycle 2 or other jquery script create the pagination


jrcollins comments:

Hi, it's a new site, so not many categories at the moment but I will be adding more. I'm not sure what the total number will be.


jrcollins comments:

A slideshow is not really what I'm looking for.


jrcollins comments:

What about if I added a page using a custom page template and referenced the url in the pagination code? Would something like that work?


Rempty comments:

Yes and assign an ID to load the content using this:
http://api.jquery.com/load/


Rempty comments:

The steps to create ajax in wordpress, all this in the functions.php:

//First you need to define to your ajax path

add_action('wp_head', 'myplugin_ajaxurl');

function myplugin_ajaxurl() {
echo '<script type="text/javascript">
var ajaxurl = "' . admin_url('admin-ajax.php') . '";
</script>';
}




//Define the function to load ajax

add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');

function more_post_ajax(){
//assign the variable
$page=($_POST['pagecat'])?$_POST['pagecat']:1;
header("Content-Type: text/html");
//Do your querys etc

//Save your data in a variable
$out = '';
$out.='';
//return the html data
die($out);
}


Now the javascript, you must include a js in your header or footer

//You can define some variables
var pageNumber = 0;

function load_posts() {
//Sum 1 to current pageNumber
pageNumber++;
//String Url
var str = '&pageNumber=' + pageNumber ;
jQuery.ajax({
type: "POST",
dataType: "html",
url: ajaxurl,
data: str,
success: function (data) {
var $data = jQuery(data);
if ($data.length) {
//Where i put the result
jQuery("#my-posts").append($data);

} else {
//If there is no results here
}
},
error: function (jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}

});
return false;
}


In this example i am using a function, but you can use a event onclick, you can add some attr to the link with the page, etc
<a class="link-page" data-page="2" href="#">2</a>

jQuery(".link-page").click(function(ev){
ev.preventDefault();
pageNumber=jQuery(this).data('page');
var str = '&pageNumber=' + pageNumber ;
jQuery.ajax({
type: "POST",
dataType: "html",
url: ajaxurl,
data: str,
success: function (data) {
var $data = jQuery(data);
if ($data.length) {
//Where i put the result
jQuery("#my-posts").append($data);

} else {
//If there is no results here
}
},
error: function (jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}

});
return false;
});


jrcollins comments:

Could you please explain in more detail? I know some basic PHP but I'm a complete beginner when it comes to Javascript/JQuery and Ajax.


Rempty comments:

There is a misstypo
$page=($_POST['pagecat'])?$_POST['pagecat']:1;
to
$page=($_POST['pageNumber'])?$_POST['pageNumber']:1;


jrcollins comments:

Ok, thanks. I'll try that.


jrcollins comments:

I'm working on it. I'll get back to you again soon.


jrcollins comments:

Hi, I created a page using a custom template to display the categories but I can't get the paging to work. When I navigate to page 2, the content displayed is the same as the first page.


Rempty comments:

Hi
Are you using this for the AJAX load?

check what of this query vars have the page number:

echo get_query_var( 'page' );
echo get_query_var( 'paged' );

$catpage =get_query_var( 'paged' )?get_query_var( 'paged' ):1;

And use it in your query array

paged' => $catpage,


jrcollins comments:

It's a page so it should be get_query_var( 'page' );. When I try echo get_query_var( 'page' );, it return "0" on the first page and then nothing on any subsequent pages.


Rempty comments:

global $wp_query;
print_r($wp_query);

And check if there is the parameter page or paged


jrcollins comments:

0WP_Query Object ( [query_vars] => Array ( [page] => 0 [pagename] => popular-categories [error] => [m] => [p] => 0 [post_parent] => [subpost] => [subpost_id] => [attachment] => [attachment_id] => 0 [name] => popular-categories [static] => [page_id] => 0 [second] => [minute] => [hour] => [day] => 0 [monthnum] => 0 [year] => 0 [w] => 0 [category_name] => [tag] => [cat] => [tag_id] => [author] => [author_name] => [feed] => [tb] => [paged] => 0 [meta_key] => [meta_value] => [preview] => [s] => [sentence] => [title] => [fields] => [menu_order] => [embed] => [category__in] => Array ( ) [category__not_in] => Array ( ) [category__and] => Array ( ) [post__in] => Array ( ) [post__not_in] => Array ( ) [post_name__in] => Array ( ) [tag__in] => Array ( ) [tag__not_in] => Array ( ) [tag__and] => Array ( ) [tag_slug__in] => Array ( ) [tag_slug__and] => Array ( ) [post_parent__in] => Array ( ) [post_parent__not_in] => Array ( ) [author__in] => Array ( ) [author__not_in] => Array ( ) [ignore_sticky_posts] => [suppress_filters] => [cache_results] => 1 [update_post_term_cache] => 1 [lazy_load_term_meta] => 1 [update_post_meta_cache] => 1 [post_type] => [posts_per_page] => 2 [nopaging] => [comments_per_page] => 50 [no_found_rows] => [order] => DESC ) [tax_query] => [meta_query] => WP_Meta_Query Object ( [queries] => Array ( ) [relation] => [meta_table] => [meta_id_column] => [primary_table] => [primary_id_column] => [table_aliases:protected] => Array ( ) [clauses:protected] => Array ( ) [has_or_relation:protected] => ) [date_query] => [post_count] => 1 [current_post] => -1 [in_the_loop] => [comment_count] => 0 [current_comment] => -1 [found_posts] => 1 [max_num_pages] => 0 [max_num_comment_pages] => 0 [is_single] => [is_preview] => [is_page] => 1 [is_archive] => [is_date] => [is_year] => [is_month] => [is_day] => [is_time] => [is_author] => [is_category] => [is_tag] => [is_tax] => [is_search] => [is_feed] => [is_comment_feed] => [is_trackback] => [is_home] => [is_404] => [is_embed] => [is_paged] => [is_admin] => [is_attachment] => [is_singular] => 1 [is_robots] => [is_posts_page] => [is_post_type_archive] => [query_vars_hash:WP_Query:private] => d68ed96762d3f3d3a7357f7bdbeff887 [query_vars_changed:WP_Query:private] => [thumbnails_cached] => [stopwords:WP_Query:private] => [compat_fields:WP_Query:private] => Array ( [0] => query_vars_hash [1] => query_vars_changed ) [compat_methods:WP_Query:private] => Array ( [0] => init_query_flags [1] => parse_tax_query ) [query] => Array ( [page] => [pagename] => popular-categories ) [queried_object] => WP_Post Object ( [ID] => 198 [post_author] => 1 [post_date] => 2016-09-20 01:52:10 [post_date_gmt] => 2016-09-20 01:52:10 [post_content] => [post_title] => Popular Categories [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => popular-categories [to_ping] => [pinged] => [post_modified] => 2016-09-20 09:48:33 [post_modified_gmt] => 2016-09-20 09:48:33 [post_content_filtered] => [post_parent] => 0 [guid] => http://www.myhomespa.net/?page_id=198 [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [filter] => raw ) [queried_object_id] => 198 [request] => SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = '198') AND wp_posts.post_type = 'page' ORDER BY wp_posts.post_date DESC [posts] => Array ( [0] => WP_Post Object ( [ID] => 198 [post_author] => 1 [post_date] => 2016-09-20 01:52:10 [post_date_gmt] => 2016-09-20 01:52:10 [post_content] => [post_title] => Popular Categories [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => popular-categories [to_ping] => [pinged] => [post_modified] => 2016-09-20 09:48:33 [post_modified_gmt] => 2016-09-20 09:48:33 [post_content_filtered] => [post_parent] => 0 [guid] => http://www.myhomespa.net/?page_id=198 [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [filter] => raw ) ) [post] => WP_Post Object ( [ID] => 198 [post_author] => 1 [post_date] => 2016-09-20 01:52:10 [post_date_gmt] => 2016-09-20 01:52:10 [post_content] => [post_title] => Popular Categories [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => popular-categories [to_ping] => [pinged] => [post_modified] => 2016-09-20 09:48:33 [post_modified_gmt] => 2016-09-20 09:48:33 [post_content_filtered] => [post_parent] => 0 [guid] => http://www.myhomespa.net/?page_id=198 [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [filter] => raw ) )
There's both "page" and "paged".


jrcollins comments:

Ok, I tried it with "paged" and it's working now.


jrcollins comments:

I meant I got the paging to work on the page using the custom template. I don't have Ajax paging on the widget working yet.


jrcollins comments:

I put this in my functions.php file:
//First you need to define to your ajax path

add_action('wp_head', 'myplugin_ajaxurl');

function myplugin_ajaxurl() {
echo '<script type="text/javascript">
var ajaxurl = "' . admin_url('admin-ajax.php') . '";
</script>';
}


//Define the function to load ajax

add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');

function more_post_ajax(){

//assign the variable

$page=($_POST['pageNumber'])?$_POST['pageNumber']:1;
header("Content-Type: text/html");
//Do your querys etc

//Save your data in a variable
$out = '';
$out.='';
//return the html data
die($out);
}


jrcollins comments:

You have the Javascript in a function too. Would it be better to place in a separate file and link to it?


Rempty comments:

You don't need use the functions.php or any function i added before, because you created your own pagination in other page.

You must use this
http://api.jquery.com/load/
If you see the example
"Load another page's list items into an ordered list."
load all li from a external URL http://api.jquery.com/resources/load.html
and insert in the ol with ID new-projects



//A example of how apply to your requeriments.

<!--This is the DIV i'll replace with the results -->
<div id="container_results">
<!-- Here go all your categories listed-->
</div>
<div class="pagination">
<a class="link-class" href="url-categorypage/page/1">1</a>
<a class="link-class" href="url-categorypage/page/1">2</a>
<a class="link-class" href="url-categorypage/page/1">3</a>
... etc
</div>

Example of your page with paginations
<header/>
<div id="results_pagination">
<!-- Here Results of Pagination-->
</div>
<footer/>

Javascript (use a js or add it to your header or footer):

jQuery(document).ready(function(){
//Attach the click event to the "a links"
jQuery("a.link-class").click(function(ev){
ev.preventDefault();
//i guess that the href have the url of the next page
var url= jQuery(this).attr("href");
//Where you want to show the results, use div id;
var container_results=jQuery("#container_results");
//Here "#results_pagination" is the ID of the div that contain the results of your custom pagination page
container_results.load(url+" #results_pagination" );
});
});




Rempty comments:

Here a live example

https://plnkr.co/edit/uc50xFBUyQ2oMqKUnsl9?p=preview

"You can see the used files in the left sidebar"


jrcollins comments:

Ok, maybe if we start from the beginning again. As of now I have the custom page set up and have added the page links to the widget.

This is the HTML markup for displaying the categories:
<div id="gridwrap" class="block1 block1_grid">
<div class="row">
<article></article>
</div>
</div>


and this is the HTML markup for the page navigation:
<div id="gridwrap" class="block1 block1_grid">
<div class="row">
<article></article>
</div>
</div>

<div class="ft-paginate">
<nav class="navigation">
<div id="navwrap" class="nav-links">
<a>page links</a>
</div>
</nav>
</div>


jrcollins comments:

Sorry, I posted the HTML for the categories display twice.


jrcollins comments:

So far in my functions.php file I have the following code:

//First you need to define to your ajax path
add_action('wp_head', 'myplugin_ajaxurl');

function myplugin_ajaxurl() {
echo '<script type="text/javascript">
var ajaxurl = "' . admin_url('admin-ajax.php') . '";
</script>';
}

//Define the function to load ajax

add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');

function more_post_ajax() {

//assign the variable
$page=($_POST['pageNumber'])?$_POST['pageNumber']:1;
header("Content-Type: text/html");

//Do your querys etc
//Save your data in a variable

$out = '';
$out.='';

//return the html data

die($out);
}


Rempty comments:

You dont need the code in the functions.php
Only the javascript, check the example.


jrcollins comments:

Here's a link to the [[LINK href="http://shoutkey.com/every"]]homepage[[/LINK]]. You can see the category widget at the bottom of the page.


jrcollins comments:

I tried placing the in the header.php file to test but it's not working:
<script>
jQuery(document).ready(function(){
//Attach the click event to the "a links"
jQuery("a.catlink").click(function(ev){
ev.preventDefault();
//i guess that the href have the url of the next page
var url= jQuery(this).attr("href");
//Where you want to show the results, use div id;
var container_results=jQuery("#gridwrap");
//Here "#results_pagination" is the ID of the div that contain the results of your custom pagination page
container_results.load(url+" #gridwrap_1" );
});
});
</script>


Rempty comments:

I'll check tomorrow in the morning is really late in my country


jrcollins comments:

Ok, thanks.


jrcollins comments:

I enqueued the script in the footer using:
function add_ajax_script() {
wp_register_script('ajax-implementation', '/wp-content/themes/codilight-child/scripts/ajax-implementation.js', array('jquery'), null, true);
wp_enqueue_script('ajax-implementation');
}

add_action( 'wp_enqueue_scripts', 'add_ajax_script' );


These are the contents of the file:
jQuery(document).ready(function(){
//Attach the click event to the "a links"
jQuery("a.catlink").click(function(ev){
ev.preventDefault();
//i guess that the href have the url of the next page
var url= jQuery(this).attr("href");
//Where you want to show the results, use div id;
var container_results=jQuery("#gridwrap");
//Here "#results_pagination" is the ID of the div that contain the results of your custom pagination page
container_results.load(url+" #gridwrap_1" );
});
});

When I click on the page link in the widget it takes me to the categories page.


Rempty comments:

there is an error in the js

$container_results.load($url + "#gridwrap_1");
change to
container_results.load($url + "#gridwrap_1");


jrcollins comments:

Ok, I tried that but now when I click to the next page nothing happens. I checked the console and it's showing this error:
Uncaught ReferenceError: $url is not defined ajax-implementation.js:10


Rempty comments:

change $url to url


Rempty comments:

change
container_results.load(url + "#gridwrap_1");
to
container_results.load(url + " #gridwrap_1");


jrcollins comments:

It's sort of working but it's loading the whole page instead of just the #gridwrap_1 element.


Rempty comments:

change
container_results.load(url + "#gridwrap_1");
to
container_results.load(url + " #gridwrap_1");


jrcollins comments:

That did it! Now I just have to fix the page links so they're working properly. Thanks for your help. I've already upvoted your answer. Is there anything else I need to do?


Rempty comments:

Your Welcome.
Please click
"Vote to award prize"


jrcollins comments:

Done. Thanks again.