Jump to content

paginate AJAX returned content


samoht

Recommended Posts

Hello all, 

I feel pretty good that I got my AJAX filter working properly. But it still needs some help. Now I am returning the content with Ajax that I want from the search filter of dropdown option (keep in mind there are several options to filter by). But the content returned is often to much to fit on one page - so I need to paginate the successfully returned html from my AJAX call. 

 

Here is where I get stumped. Do I setup a normal page nav outside the AJAX area? 

</div><!-- AJAX return container-->

    	<nav class="pagenav">
			<ul id="pag-link">
				<li class="old"><?php next_posts_link('« Older Sermons', $sermons_query->max_num_pages) ?></li>
				<li class="new"><?php previous_posts_link('Newer Sermons »', $sermons_query->max_num_pages) ?></li>
			</ul>
		</nav>	

IF so, how do I update the links info? 

 

or do I keep the page nav inside the AJAX area but use some custom code to retrieve the proper link? (I tried using the normal wordpress page nav functions in my php function but they provide the url of the page that the php function is on, not the actual page being viewed). 

 

Do I need to make a separate AJAX call to a function that just builds my links? or is there a way to do it with my main call? 

 

Here is my AJAX call:

	//Listen for the menu's to change except the main filter_by dropdown
	var ids = ['filter_preacher_dropdown', 'filter_sort_by_dropdown', 'filter_per_page_dropdown', 
	'filter_series_dropdown', 'filter_service_dropdown', 'filter_tag_dropdown', 'filter_book_dropdown', 'filter_year_dropdown'];
	$('#' + ids.join(',#')).change(function(e) {
		var pt = [ "preacher","series","service" ];
		if($.inArray(this.name, pt)!==-1){
		var mk 	= this.name;
		var mv 	= $(this).val();
		var ppp = $("#filter_per_page_dropdown").val();
		var ob 	= $("#filter_sort_by_dropdown").val();
		var data = {
			action: 'filter_sermons', 
			meta_key: mk, 
			meta_value: mv, 
			posts_per_page: ppp
			};
			$.post(mbsb_ajaxurl, data, function(response) {
				$('#sermonlists').fadeOut('slow', function() {
					$(this).html(response)
				}).fadeIn('slow');
			});
		}

and here is my php function (slightly paired down for viewing ease):

//ajax for sermons filter
add_action('wp_ajax_filter_sermons', 'check_ajax'); 
add_action('wp_ajax_nopriv_filter_sermons', 'check_ajax');


function check_ajax() {
	global $wpdb, $paged, $max_num_pages;
//check if filter is on post_type
if($_POST['meta_key']){
	$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
	$mk = '"'.$_POST['meta_key'].'"';
	$mv = intval($_POST['meta_value']);
	$ppp = intval($_POST['posts_per_page']);
	$offset = ($paged - 1) * $ppp;
	$sermons = $wpdb->get_results("SELECT SQL_CALC_FOUND_ROWS sermons.* FROM {$wpdb->prefix}posts AS sermons, {$wpdb->prefix}postmeta WHERE meta_key = {$mk} AND meta_value = {$mv} AND sermons.ID = {$wpdb->prefix}postmeta.post_id LIMIT {$offset}, {$ppp}", OBJECT);
	$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
    $max_num_pages = ceil($sql_posts_total / $ppp);	
}elseif($_POST['name']){	
	//another custom query
}elseif ($_POST['book_number']){
	//another custom query

}
    $posts = get_posts();                		// returns posts in an array

	if($sermons) {
		global $post; 
		foreach ($sermons as $post){
		setup_postdata($post); 
		
			//custom query info returned here
		}

          //Would the Pagination for the AJAXED content go here?

	}else{ ?>
    <h2 class="center">Not Found</h2>
    <p class="center">Sorry, but you are looking for something that isn't here.</p>
 <?php 
 } 

	die();
}
Link to comment
Share on other sites

I would return all the requisite data in JSON format. Then use JavaScript to populate the page and set the necessary pagination controls. I'd suggest the data should be sent as a multi-dimensional array something like this:

$return = array(
'page' => 2,
'total_pages' => 10,
'page_data' = array(
    0 => array(data_for_first_record),
    1 => array(data_for_second_record),
    2 => array(data_for_third_record),
    . . .
    )

)
Link to comment
Share on other sites

Well I tried something else which I thought would work, but not so much. 

 

I added another ajax call to load the pagelinks 

	//Listen for the menu's to change except the main filter_by dropdown
	var ids = ['filter_preacher_dropdown', 'filter_sort_by_dropdown', 'filter_per_page_dropdown', 
	'filter_series_dropdown', 'filter_service_dropdown', 'filter_tag_dropdown', 'filter_book_dropdown', 'filter_year_dropdown'];
	$('#' + ids.join(',#')).change(function(e) {
		var pt = [ "preacher","series","service" ];
		if($.inArray(this.name, pt)!==-1){
		var mk 	= this.name;
		var mv 	= $(this).val();
		var ppp = $("#filter_per_page_dropdown").val();
		var ob 	= $("#filter_sort_by_dropdown").val();
		var lp	= $(location).attr('href');
		var data = {
			action: 'filter_sermons', 
			meta_key: mk, 
			meta_value: mv, 
			posts_per_page: ppp,
			linkpage: lp
			};
			$.post(mbsb_ajaxurl, data, function(response) {
				$('#sermonlists').fadeOut('slow', function() {
					$(this).html(response);
					$('#pagination').load(lp);
				}).fadeIn('slow');
			});
		}
	});
       //NEW AJAX call for pagelinks
	$('#pagination').on('click', '#pag-link > li > a', function(){
		var link = $(this).attr('href');

		$.ajax({
			url: $location().attr('href'),
			type:'GET',
			dataType: 'json',
			success: function(listings){
				$('#pagination').html(listings);
			} // End of success function of ajax form       
		}); // End of ajax call                            

		return false;
	});	
	

but that just filled my #pagination div with the entire page again?

Link to comment
Share on other sites

Sorry the above code has an error in it, I knew it was there but posted to soon and it would not let me edit? 

Anyway the error is $('#pagination').load(lp); on line 133

But I removed that and still no luck.

 

Am I correct in thinking that I should have an on click event for the link to be sure I serve up the correct paginated content?

Otherwise it would just default to the normal php page right??

Link to comment
Share on other sites

Thanks Psycho,

 

forgive me for this probably dumb question, but are you saying skip the php function all together? 

 

Not at all. I'm saying the PHP code should get all the data you need: total records, total pages, current pages, etc. AND the data to display on the current page. You can then put all the data into an array and then pass it in JSON format back to the calling AJAX request. Then use JavaScript to tear apart the data and populate/enable/disable the pagination controls, the grid, etc.

Link to comment
Share on other sites

I see. Sorry for the misunderstanding. That is why you started with $return = array (...

 

I am still a little foggy on how this would work with populating the page and the links. For example: you said 'page' => 2, at the beginning of your example array. I'm not sure where the 2 would come from. Would that be a php variable passed into the return array or would it be derived from somewhere else?

 

Again, forgive me if I am missing the obvious.

 

Thanks, 

Link to comment
Share on other sites

Yes, you would determine ALL the relevant data needed in PHP and then pass the results back to the AJAX call and do whatever you need to using JavaScript. That's the correct way to do it and maintain separation of business logic and data. However, there is a simpler way.

 

On your page identify the different containers to hold the dynamic content. I would assume, for example, that you would have a container for the grid and another for the pagination controls. You could use the PHP logic to build the HTML content for those containers and then pass them back to the AJAX call and simply drop those pieces of content into the appropriate containers.

Link to comment
Share on other sites

Thanks for you patience with me. 

 

This is what I have changed my PHP function to look like to send JSON data back to my ajax 

if($_POST['meta_key']){
	$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
	$mk = '"'.$_POST['meta_key'].'"';
	$mv = intval($_POST['meta_value']);
	$ppp = intval($_POST['posts_per_page']);
	$offset = ($paged - 1) * $ppp;
	$sermons = $wpdb->get_results("SELECT SQL_CALC_FOUND_ROWS sermons.* FROM {$wpdb->prefix}posts AS sermons, {$wpdb->prefix}postmeta WHERE meta_key = {$mk} AND meta_value = {$mv} AND sermons.ID = {$wpdb->prefix}postmeta.post_id LIMIT {$offset}, {$ppp}", OBJECT);
	$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
    $max_num_pages = ceil($sql_posts_total / $ppp);	
	
	$return =  json_encode(array('page': $paged, 'total_pages': $max_num_pages, 'sermons': $sermons));

	echo $return;
	exit;
	}

I believe that this is sending back the multi-dimesional array with all the data I requested, but now I do not know how to parse that to populate my page or the navigation? 

 

I assume that I need to loop with .each?

	$.post(mbsb_ajaxurl, data, function(response) {
	console.log(response.length);

		$.each($.parseJSON(response), function(idx, obj) {
			console.log(obj.post_title);
			//$('.main_title').html(obj.post_title);
		});

	});

but this returns a length of 187 (seems a little low? but it could be right)

and a Uncaught SyntaxError: Unexpected token <

 

I guess that means my JSON array is not correct? 

Link to comment
Share on other sites

ok I changed my PHP function to this:

	$serms = json_encode($sermons);
	$return =  json_encode(array('page' => $paged, 'total_pages' => $max_num_pages, 'sermons' => $serms ));

which spits out: 

{
    "page": 1,
    "total_pages": 2,
    "sermons": "[{\"ID\":\"165\",\"post_author\":\"1\",\"post_date\":\"2014-01-29 10:45:00\",\"post_date_gmt\":\"2014-01-29 21:06:20\",\"post_content\":\"The gospel grammar of the New Testament is not new - but perfectly structured in the judgment oracle against Philistia. In the final verse the great apologetic question, \\\"what shall one tell...\\\" is answered with both the indicative (The Lord has founded Zion) and the imperative (the afflicted of His people shall rest in it). This is the essential Q&A of all life!\",\"post_title\":\"The Lord Has Founded Zion\",\"post_excerpt\":\"\",\"post_status\":\"publish\",\"comment_status\":\"open\",\"ping_status\":\"open\",\"post_password\":\"\",\"post_name\":\"the-lord-has-founded-zion\",\"to_ping\":\"\",\"pinged\":\"\",\"post_modified\":\"2014-01-29 10:45:00\",\"post_modified_gmt\":\"2014-07-01 19:07:13\",\"post_content_filtered\":\"\",\"post_parent\":\"0\",\"guid\":\"http:\\/\\/localhost\\/newomega\\/?post_type=mbsb_sermon&p=165\",\"menu_order\":\"0\",\"post_type\":\"mbsb_sermon\",\"post_mime_type\":\"\",\"comment_count\":\"0\"},{\"ID\":\"287\",\"post_author\":\"1\",\"post_date\":\"2014-06-29 10:45:00\",\"post_date_gmt\":\"2014-06-29 10:45:00\",\"post_content\":\"Isaiah begins his conclusion to the book of the king with an historical narrative that demonstrates the certainty and trustworthy nature of God's Word. \",\"post_title\":\"In Whom Are You Trusting\",\"post_excerpt\":\"\",\"post_status\":\"publish\",\"comment_status\":\"open\",\"ping_status\":\"closed\",\"post_password\":\"\",\"post_name\":\"in-whom-are-you-trusting\",\"to_ping\":\"\",\"pinged\":\"\",\"post_modified\":\"2014-06-29 10:45:00\",\"post_modified_gmt\":\"2014-06-29 10:45:00\",\"post_content_filtered\":\"\",\"post_parent\":\"0\",\"guid\":\"http:\\/\\/localhost\\/newomega\\/?post_type=mbsb_sermon&p=287\",\"menu_order\":\"0\",\"post_type\":\"mbsb_sermon\",\"post_mime_type\":\"\",\"comment_count\":\"0\"}]"
}

I ran that through a json validator and it came back valid JSON 

 

So I know I giving my AJAX response valid JSON but it still is choking. My length is a much more respectable 6382

but I get 

Uncaught SyntaxError: Unexpected token < 

 

How can I get a SyntaxError if my JSON is valid? 

Link to comment
Share on other sites

I fixed my JSON. I should not have been double encoding so it now looks like this:

{
    "page": 1,
    "total_pages": 2,
    "sermons": [
        {
            "ID": "165",
            "post_author": "1",
            "post_date": "2014-01-29 10:45:00",
            "post_date_gmt": "2014-01-29 21:06:20",
            "post_content": "The gospel grammar of the New Testament is not new - but perfectly structured in the judgment oracle against Philistia. In the final verse the great apologetic question, \"what shall one tell...\" is answered with both the indicative (The Lord has founded Zion) and the imperative (the afflicted of His people shall rest in it). This is the essential Q&A of all life!",
            "post_title": "The Lord Has Founded Zion",
            "post_excerpt": "",
            "post_status": "publish",
            "comment_status": "open",
            "ping_status": "open",
            "post_password": "",
            "post_name": "the-lord-has-founded-zion",
            "to_ping": "",
            "pinged": "",
            "post_modified": "2014-01-29 10:45:00",
            "post_modified_gmt": "2014-07-01 19:07:13",
            "post_content_filtered": "",
            "post_parent": "0",
            "guid": "http://localhost/newomega/?post_type=mbsb_sermon&p=165",
            "menu_order": "0",
            "post_type": "mbsb_sermon",
            "post_mime_type": "",
            "comment_count": "0"
        },
        {
            "ID": "287",
            "post_author": "1",
            "post_date": "2014-06-29 10:45:00",
            "post_date_gmt": "2014-06-29 10:45:00",
            "post_content": "Isaiah begins his conclusion to the book of the king with an historical narrative that demonstrates the certainty and trustworthy nature of God's Word. ",
            "post_title": "In Whom Are You Trusting",
            "post_excerpt": "",
            "post_status": "publish",
            "comment_status": "open",
            "ping_status": "closed",
            "post_password": "",
            "post_name": "in-whom-are-you-trusting",
            "to_ping": "",
            "pinged": "",
            "post_modified": "2014-06-29 10:45:00",
            "post_modified_gmt": "2014-06-29 10:45:00",
            "post_content_filtered": "",
            "post_parent": "0",
            "guid": "http://localhost/newomega/?post_type=mbsb_sermon&p=287",
            "menu_order": "0",
            "post_type": "mbsb_sermon",
            "post_mime_type": "",
            "comment_count": "0"
        }
    ]
}

which is still valid JSON and is still giving me the SyntaxError : Unexpected token <

 

I don't see where that could be coming from?

Link to comment
Share on other sites

  • 3 weeks later...

Based on a quick Google search of that error, the problem is likely that the AJAX call is getting back an error page. You displayed the JSON code that you state is being generated, but are you sure that is what is getting returned?

 

If you get back an error page it may be formatted in HTML. E.g. rough example: "<html><body>404 Not Found</body</html>",

 

What do you get when you request the PHP page directly, i.e. not through AJAX? What is displayed on the page?

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.