I have a problem with WordPress and Ajax.
This is my JavaScript part (I trimmed it a bit):
var posts = $.ajax({
type: 'POST',
url: ajaxurl,
async: false,
dataType: 'json',
data: { action: 'myAjaxFunc' },
done: function(response) {
return response;
}
}).responseText;
$.each(posts, function() {
$('#someSelect').append( $('<option</option>').text(this.name).val(this.id) );
});
My PHP code is as follows:
function myAjaxFunc() {
$posts = get_posts( array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
'post_type' => 'my-post-type',
'post_status' => array( 'publish', 'draft' )
) );
$list = array();
foreach ( $posts as $post ) {
$list[] = array(
'id' => $post->ID,
'name' => $post->post_title,
'link' => get_permalink( $post->ID ),
);
}
header("Content-type: application/json");
echo json_encode( $list );
die;
}
add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' );
add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' );
The script gets the Ajax response from admin-ajax. Unfortunately the console throws an error when it gets to the each
statement in the JavaScript code... it says:
"Uncaught TypeError: Cannot use 'in' operator to search for '4' in Array".
If I do a console.log of my "posts" var I get a string 'Array'. No matter how I pass the $list
variable in PHP it will always return a string. The query returns posts elsewhere, so it's not empty. I tried without json_encode
, with and without declaring header, using wp_send_json()
, putting ob_clean()
before echoing the array, putting the array into an array... But it always gets into ajax
as a string Array
and each
cannot cycle through it.
This should be a very simple thing and I can't understand why it's not working. I don't have other JavaScript or PHP errors or warnings and everything else runs fine.
I have a problem with WordPress and Ajax.
This is my JavaScript part (I trimmed it a bit):
var posts = $.ajax({
type: 'POST',
url: ajaxurl,
async: false,
dataType: 'json',
data: { action: 'myAjaxFunc' },
done: function(response) {
return response;
}
}).responseText;
$.each(posts, function() {
$('#someSelect').append( $('<option</option>').text(this.name).val(this.id) );
});
My PHP code is as follows:
function myAjaxFunc() {
$posts = get_posts( array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
'post_type' => 'my-post-type',
'post_status' => array( 'publish', 'draft' )
) );
$list = array();
foreach ( $posts as $post ) {
$list[] = array(
'id' => $post->ID,
'name' => $post->post_title,
'link' => get_permalink( $post->ID ),
);
}
header("Content-type: application/json");
echo json_encode( $list );
die;
}
add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' );
add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' );
The script gets the Ajax response from admin-ajax. Unfortunately the console throws an error when it gets to the each
statement in the JavaScript code... it says:
"Uncaught TypeError: Cannot use 'in' operator to search for '4' in Array".
If I do a console.log of my "posts" var I get a string 'Array'. No matter how I pass the $list
variable in PHP it will always return a string. The query returns posts elsewhere, so it's not empty. I tried without json_encode
, with and without declaring header, using wp_send_json()
, putting ob_clean()
before echoing the array, putting the array into an array... But it always gets into ajax
as a string Array
and each
cannot cycle through it.
This should be a very simple thing and I can't understand why it's not working. I don't have other JavaScript or PHP errors or warnings and everything else runs fine.
Share Improve this question edited Mar 3, 2019 at 20:21 Peter Mortensen 2682 silver badges10 bronze badges asked Nov 17, 2014 at 19:40 unfulviounfulvio 1,8347 gold badges32 silver badges63 bronze badges 3- What do you see when you go to example/wp-admin/admin-ajax.php?action=myAjaxFunc – czerspalace Commented Nov 17, 2014 at 20:09
- Any progress on your question? Could you please follow up? – kaiser Commented Apr 15, 2015 at 11:27
- oh... this is from 5 months ago... I did answer to my own question by the way the next day I posted it, using bits of BODA82 answer - I just didn't marked it as the correct answer; @toscho added his follow up much later yesterday I can't verify if his answer is also good now, it makes sense though – unfulvio Commented Apr 16, 2015 at 21:13
3 Answers
Reset to default 8BODA82's answer helped, but eventually I realized that I should have replaced responseText
with responseJSON
method in my JavaScript code. In the example below I was storing the Ajax response results in a variable. I didn't know there was a specific method to get the response in JSON. In a such way the object/array with get_posts()
results is returned correctly and not as a string:
posts = $.ajax({
type: 'GET',
url: ajaxurl,
async: false,
dataType: 'json',
data: { action : 'getHotelsList' },
done: function(results) {
// Uhm, maybe I don't even need this?
JSON.parse(results);
return results;
},
fail: function( jqXHR, textStatus, errorThrown ) {
console.log( 'Could not get posts, server response: ' + textStatus + ': ' + errorThrown );
}
}).responseJSON; // <-- this instead of .responseText
Note to self, but also general advice: if you can't fix something in the evening it's a sign you should go to bed, read a book, and count stars. An answer will be found the next morning, the earlier the better :D
Almost there with your PHP function. No need to set the header. (Edit: Also, assuming get_posts()
is actually returning results.)
function myAjaxFunc() {
$posts = get_posts( array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
'post_type' => 'my-post-type',
'post_status' => array( 'publish', 'draft' )
) );
$list = array();
foreach ( $posts as $post ) {
$list[] = array(
'id' => $post->ID,
'name' => $post->post_title,
'link' => get_permalink( $post->ID ),
);
}
echo json_encode( $list );
die;
}
add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' );
add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' );
And your Javascript:
$.ajax({
url: "<?php bloginfo('url'); ?>/wp-admin/admin-ajax.php",
type: "POST",
data: "action=myAjaxFunc",
success: function(results) {
var posts = JSON.parse(results);
console.log(results);
$.each(posts, function() {
$('#someSelect').append( $('<option></option>').text(this.name).val(this.id) );
});
},
error: function() {
console.log('Cannot retrieve data.');
}
});
There is a way out. Use complete
instead of success
or done
:
posts = $.ajax({
type: 'GET',
url: ajaxurl,
async: false,
dataType: 'json',
data: { action : 'getHotelsList' },
complete: function(results) {
And try to remove async:false
if the problem persists.