This is my first attempt at adding ajax to a WordPress plugin. I have had some success but there are a couple areas where I am stuck. I learned a tremendous amount from everyone here so I hope I haven’t worn out my welcome? 😉
Here’s the scenario. I am attempting to use ajax to prevent page reload after updating a list of question answers that are individual forms. This is part of an admin page to a WordPress plugin but I think I’ve covered my bases with WP since it does work to a point.
The PHP:
//Update an answer
function ccd_ex_update_answer() {
global $wpdb;
$wpdb->update( $wpdb->prefix . 'ccd_ex_answers', array(
'answer' => $_POST['answer'],
'sort' => $_POST['sort'],
'correct' => $_POST['correct'],
'question_id' => $_POST['question_id']
), array(
'ID' => $_POST['id']
)
);
}
add_action( 'wp_ajax_ccd_ex_update_answer', 'ccd_ex_update_answer' );
The jQuery:
//Update Answers
jQuery(document).ready(function($) {
$('.aupdatebutton').live("click", function(){
var thisupdate = $(this).data('aupdate');
$(thisupdate).submit(function(){
var answer = $(".answer").val();
var sort = $(".sort").val();
var correct = $(".correct").val();
var question_id = $(".question_id").val();
var id = $(".id").val();
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: 'ccd_ex_update_answer',
answer: answer,
sort: sort,
correct: correct,
question_id: question_id,
id: id
},
success: function(data, textStatus, XMLHttpRequest){
jQuery("#test-div").html('').fadeIn(500);
jQuery("#test-div").append("Answer Updated!").fadeOut(3000);
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
return false;
});
});
});
Problem 1. As it is now, the ajax calls work to update the field associated with .answer, but when I try to update any of the other fields in the form, it doesn’t happen. What am I missing in this regard?
Problem 2. I would like to add the ability to update the list of answers to reflect the newly updated content using ajax calls as well. How do I add the proper callback to do this? EDIT: Problem 1 made this thread so lengthy that I’ll take this question to a new thread.
These answer lists are currently being created in a loop like so:
<?php
$aresult = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "ccd_ex_answers WHERE question_id = " . $qrow->id . " ORDER BY sort ASC");
foreach( $aresult as $key => $arow ) {
?>
<form id="update-answer-<?php echo $arow->question_id."-".$arow->id; ?>" action="" method="post">
<input type="hidden" class="id" name="id" value="<?php echo $arow->id; ?>" />
<input type="hidden" class="question_id" name="question_id" value="<?php echo $qrow->id; ?>" />
<div style="float:left;">
<input type="text" style="width:40px;margin-right:15px;" class="sort" name="sort" value="<?php echo $arow->sort; ?>"/>
</div>
<div style="float:left;">
<input type="text" style="width:480px;" class="answer" name="answer" value="<?php echo $arow->answer; ?>"/>
</div>
<div style="float:left;">
<select class="correct" name="correct">
<option value="0"<?php selected( 0 , $arow->correct ); ?>>No</option>
<option value="1"<?php selected( 1 , $arow->correct ); ?>>Yes</option>
</select>
</div>
<div>
<input type="submit" name="aupdate" data-aupdate="#update-answer-<?php echo $arow->question_id."-".$arow->id; ?>" value="Update" class="aupdatebutton ccd-ex-show-questions toggletable<?php echo $qrow->id; ?>"/>
<input type="submit" name="adelete" value="Delete" class="ccd-ex-show-questions toggletable<?php echo $qrow->id; ?>"/>
</div>
<div style="clear:both;"></div>
</form>
<?php
}
?>
I’m sort of an intermediate noob in the areas of jQuery and js in general and, like I said, this is my first attempt at ajax. I’m happy to have things over explained to me if it avoids important pieces of knowledge flying over my head.
I’ll stay close in case I’ve left out anything important.
Thank you!
UPDATE:
It occurs to me that perhaps the problem with the fields that don’t update is because of their database structure? The field that updates is a VARCHAR, but the two that don’t are INT and BOOLEAN… not sure if that makes a difference or not. It didn’t when the function was entirely PHP.
UPDATE2:
Corrected a typo in the code that still had no affect on either problem.
UPDATE2:
Here are the results of outputing debug info to console, as per brandwaffel’s suggestion:
int(0)
0
UPDATE3:
In further debugging, I wrote each individual variable to the console and no matter which answer I update in the list of answers, the variables reflect the form/fields in the first position of the list. I now see that my original belief that only the answer field was updating was wrong.
What really appears to be happening is that the first item in the list updates as it should, and any others fail, which is probably due to the content of the jQuery variables.
Question now seems to be how do I adjust my variables so they are populated with the proper instance of the form fields?
In case it helps to visualize all this, here is a screenshot of the admin page. The current problems are only relate to the function(s) for updating an Answer.
UPDATE4 – FINIAL WORKING VERSION:
Here is the final version of the jQuery. Although there was good advice about the other code within the comments, the solution to my question was within the jQuery. The solution was to properly define the instance from which the variables are populated.
Working jQuery:
//Update Answers
jQuery(document).ready(function($) {
$('.aupdatebutton').live("click", function(){
var thisupdate = $(this).data('aupdate');
$(thisupdate).submit(function(){
// Get the proper instance of the form fields for the variables
var answer = $(this).find('.answer').val();
var sort = $(this).find('.sort').val();
var correct = $(this).find('.correct').val();
var question_id = $(this).find('.question_id').val();
var id = $(this).find('.id').val();
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: 'ccd_ex_update_answer',
answer: answer,
sort: sort,
correct: correct,
question_id: question_id,
id: id
},
success: function(data, textStatus, XMLHttpRequest){
jQuery("#test-div").html('').fadeIn(500);
jQuery("#test-div").append("Answer Updated!").fadeOut(3000);
console.log(data);
console.log(answer);
console.log(sort);
console.log(correct);
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
return false;
});
});
});
UPDATE: I think you’re on to something with id problem. Currently, your jQuery is grabbing the .id field, which will get the first id in your list of ids. You need to establish a context for the jQuery to look inside the particular question element. Try
and so on for all the elements you’re submitting to the ajax endpoint.
/update
It looks like you’ve got this:
where you probably want this:
To test this further, I would recommend debugging out the result of the $wpdb->update call
Then in the ajax success handler, just add this:
and you’ll see the result of your ajax response (which should be an array of the rows altered in the update query).
Also, are you seeing any errors in the JS console when you click the submit button?