Create WooCommerce custom Order meta via AJAX on thank you page - php

I am trying to use update_meta_data via AJAX on the WooCommerce thank you page but I am stuck.
Here is what I have so far:
//Following function gets called from the page already
function renderForm() {
echo "<script>
jQuery(document).ready(function() {
$('body').on('click', '#button', function(){
$.ajax({
type: 'POST',
url: 'https://thepropdrop.com/wp-admin/admin-ajax.php',
data: {
action: 'create_user_meta'
},
success: function(textStatus){
console.log('Success');
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert('errorThrown');
}
});
});
});
</script>";
}
add_action("wp_ajax_create_user_meta", "create_user_meta");
add_action("wp_ajax_nopriv_create_user_meta", "create_user_meta");
function create_user_meta() {
$order = wc_get_order($order_id);
$order->update_meta_data('hasAnswered', 'Yes');
$order->save();
die();
}
Any help you could provide would be greatly appreciated.
EDIT - My related code, that will provide some context:
Here is the button on the thankyou.php:
<span class="button gameStart">
Let's do this
</span>
<script>
jQuery(document).ready(function() {
$('.gameStart').click(function(event){
$(this).remove();
$('.gameHeader').remove();
$('.gamePage .gameContainer').css('display', 'block');
$.ajax({
type: 'GET',
url: '<?php echo admin_url("admin-ajax.php");?>',
data: {
action: 'CCAjax'
},
success: function(textStatus){
$( '.gameForm' ).prepend( textStatus );
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
});
});
</script>
<div class="gameContainer">
<div class="timerWrapper">
<div id="timer">
</div>
</div>
<div class="gameForm">
<h3>Which of the following countries has the largest land mass?</h3>
<div id='answerSubmitButton'>Submit answer</div>
</div>
</div>
Then functions.php:
function CCAjax() {
get_template_part('template-parts/game');
die();
}
add_action('wp_ajax_CCAjax', 'CCAjax');
Then the game.php:
<?php
renderForm();
?>
Now here is the full render form function (It pulls 3 potential answers from DB and also has a countdown timer, hence why i didnt post it all i didnt want to confuse)
function renderForm() {
// Fetch contries object
global $wpdb;
$results = $wpdb->get_results("select * from ( select *,#curRow :=#curRow + 1 as row_number from ( select * from ( select * from wpCountriesDB order by rand() limit 3 )b order by Mass desc )a JOIN (select #curRow :=0)r)x order by RAND()");
// Create array for answers
if(!empty($results)) {
$i = 1;
foreach ($results as $r) {
echo "<div class='answerWrapper'>
<span class='questionNumber'><span>$i</span></span>
<label class='label' for='radio$i'>".$r->Country."</label>
<input type='radio' id='radio$i' name='like' value='$r->row_number' />
</div>";
$i++;
}
}
// Display timer and check answer correct
echo "<script>
var timeLeft = 3000;
var elem = document.getElementById('timer');
var timerId = setInterval(countdown, 1000);
function countdown() {
if (timeLeft < 0) {
clearTimeout(timerId);
$('#answerSubmitButton').click();
} else {
elem.innerHTML = timeLeft + 's';
timeLeft--;
}
}
jQuery(document).ready(function() {
$('body').on('click', '#answerSubmitButton', function(){
var fetchInput = document.querySelector('.answerWrapper input[name=\'like\']:checked');
var fetchSelected = fetchInput.value;
if (fetchSelected == 1) {
$.ajax({
type: 'POST',
url: 'ajaxURL',
data: {
action: adding_custom_meta
},
success: function(textStatus){
console.log('Success');
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert('errorThrown');
}
});
} else {
console.log('incorrect')
}
});
});
</script>";
}
add_action("wp_ajax_create_user_meta", "create_user_meta");
add_action("wp_ajax_nopriv_create_user_meta", "create_user_meta");
function create_user_meta() {
$order = wc_get_order($order_id);
$order->update_meta_data('hasAnswered', 'Yes');
$order->save();
die();
}
Do i have to pass the Order ID at the very start?

Update (since your gave some context with the missing code):
Yes you have to pass the Order ID at the very start from your thankyou page (template).
You need to rethink differently your code, as you can't pass the order ID to your renderForm() function. The order ID is required to be passed through jQuery Ajax to your PHP Wordpress Ajax function that need it (to add to the order the custom meta data).
Also another mistake is (2 times):
jQuery(document).ready(function() {
that need to be instead (as you are using the jQuery shortand $):
jQuery(document).ready(function($) {
or (the same) in a shorter way:
jQuery(function($) {
Original answer:
There is some errors and missing things in your script, like the order Id that need to be passed through jQuery ajax to your PHP Wordpress/Ajax function that will add the custom meta data…
Also you don't provide in your code, the displayed button output…
So Here it is a complete example, based on your revisited code, that will display the button on Order received (thankyou) page and will add custom meta data to your order:
// PHP Wordpress AJAX: Add custom meta data to the Order
add_action("wp_ajax_adding_custom_meta", "adding_custom_order_metadata");
add_action("wp_ajax_nopriv_adding_custom_meta", "adding_custom_order_metadata");
function adding_custom_order_metadata() {
if( isset($_POST['order_id']) && $_POST['order_id'] > 0 ){
update_post_meta(esc_attr($_POST['order_id']), '_has_answered', 'Yes');
echo json_encode($_POST['order_id']);
}
die();
}
// Display a button on thankyou page (+ jQuery Ajax script)
add_action( 'woocommerce_thankyou', 'jquery_thank_you_page', 90, 1 );
function jquery_thank_you_page( $order_id ) {
// Display the button on thankyou page
echo ''.__("Update").'';
// The jQuery script (Ajax)
?>
<script type="text/javascript">
jQuery(function($) {
$('body').on('click', '#button', function(e){
e.preventDefault();
$.ajax({
type: 'POST',
url: '<?php echo admin_url("admin-ajax.php");?>',
data: {
'action': 'adding_custom_meta',
'order_id': '<?php echo $order_id; ?>'
},
success: function(response){
console.log(response); // Just for testing
},
error: function(error){
console.log(error); // Just for testing
}
});
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Using update_post_meta() function is much better and lighter alternative than calling an instance of the WC_Order Object and use after the save() method.
I have changed the order custom meta key from hasAnswered to _has_answered
On "Order received" page, the displayed button (the order Id come back, see in the console):
In the database, the custom post meta data is created:

Something like this
function renderForm($order_id) { //add an argument
echo "<script>
jQuery(document).ready(function() {
$('body').on('click', '#button', function(){
$.ajax({
type: 'POST',
url: 'https://thepropdrop.com/wp-admin/admin-ajax.php',
data: {
action: 'create_user_meta',
order_id: {$order_id} //add to your request data
},
success: function(textStatus){
console.log('Success');
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert('errorThrown');
}
});
});
});
</script>";
}
Then in your AJAX callback
function create_user_meta() {
if(empty($_POST['order_id'])) {
//return some error message
die();
}
$order = wc_get_order($_POST['order_id']); //get the id from the request
$order->update_meta_data('hasAnswered', 'Yes');
$order->save();
die();
}
As there is no way for me to know how you call renderForm there is no way for me to know how to put the order id in it. But at some point it will have to be either an argument or part of an argument (in the case of shortcode $attr such as [renderForm order_id=45]).
You may be also able to use something like
$order_id = get_the_ID();
Or
$order = get_post();
$order_id = $order->ID;
Depending on the context of how you use renderForm, you probably cant use them in the AJAX callback because it's a new request so you lose any of that context you had when building the page.
Hope that makes sense.
Not tested, but ... maybe it will work ... it should in theory.

Related

Sweet alert in ajax and php content not working

I'm trying to get a value from my database and then run an update using sweet alert pop-up but it is not working. The alert seem to pop-up and once the value is entered, it displays the value entered but not working. below is my actual ajax code:
viewproduct.php
<script>
$(document).ready(function() {
$('.btnupdatestock').click(function() {
var id = $(this).attr("id");
//var new_stock = $(this).val();
swal("Add Stock:", {
content: "input",
})
.then((updateStock) => {
$.ajax({
type: 'POST',
url: 'stock-in.php',
data:{
stock_up: updateStock,
},
success: function(data){
swal(`Updated: ${updateStock}`);
},
error: function(data){
swal(`Error updating: ${updateStock}`);
}
});
});
});
});
</script>
the above method was designed to trigger sql in stock-in.php and the code in stock-in.php is below:
<?php
include_once'connectdb.php';
if($_SESSION['useremail']=="" OR $_SESSION['role']=="Admin"){
header('location:index.php');
}
$idd=$_GET['id'];
$select=$pdo->prepare("select * from tbl_product where pid=$idd");
$select->execute();
while($row=$select->fetch(PDO::FETCH_OBJ)){
$productName = $row['pname'];
$oldstock = $row['pstock'];
//$id=$_POST['uid'];
$stockup=$_POST['stock_up'];
alert('I clicked');
$new_stock = $oldstock + $stockup;
$sql="UPDATE `tbl_product` SET `pstock` = ? WHERE pid= ? ";
$update=$pdo->prepare($sql);
$update->execute([$new_stock, $idd]);
if($result){
echo'Stock updated!';
}else{
echo'Error in updating stock';
}
}
?>
below is a picture of my UI that shows pop-up but it's not updating.
This is what I intend to do: If a user clicks on update and enters a value say 50, it should retrieve the old stock (database, say 100) and add to the new stock (value entered, say 50) and then update the database with 150. I am stuck here and any help would be appreciated. Thanks.
$(document).ready(function() {
$('.btnupdatestock').click(function() {
swal("Add Stock:", {
buttons: true,
closeModal: true,
content: "input",
}).then((updateStock) => {
if (updateStock === "") {
swal("You need to write something!");
return false
}else{
$.ajax({
type: 'POST',
url: 'stock-in.php',
data:{
stock_up: updateStock
<?php
echo ', id: '.$row->pid.' '
?>
<?php
echo ', oldstock: '.$row->pstock.' '
?>
},
success: function(data){swal(`Updated: ${updateStock}`);},
error: function(data){swal(`Error updating: ${updateStock}`);}
});
}
});
});
});
The major issue I had was I didn't make the SQL query global at the top of my page and then applied '.$row->pid.'

two ajax responses in WP

I am using ajax to load data when clicking a link in WordPress.
The request returns the response 2 times in one click.
The Code:
add_action( 'wp_ajax_pt_add_to_compare', 'pt_add_to_compare_callback' );
add_action( 'wp_ajax_nopriv_pt_add_to_compare', 'pt_add_to_compare_callback' );
function pt_add_to_compare_callback() {
$response = do_shortcode('[aps_product_specs id="'.$_POST['id'].'"]');
echo $response;
exit;
}
and the Ajax Part is
$(document).on('click', '.aps-comp-results li a', function (e) {
e.preventDefault();
var link = $(this).attr('href');
var id = getQueryVariable(link, "id");
$.post({
url: ptobject.ajaxurl,
data: {
id: id,
action: 'pt_add_to_compare',
},
success: function (response) {
$('.comparison-row').append('<div class="col-md-4">' + response + '</div>');
}
});
});
So Why this code returns the response twice?

Stopping ajax code from running based on result from database

I have a bootbox dialog with a button named save in a view called table_data.php and I would like to determine whether the Ajax post to database will be done based on a result obtained from the database.
I want the data only to be saved when the database query in home_model.php does not return any rows. However, when I do it, it does not work. It is a cms and I am using codeigniter framework.
My page is blank. And nothing appears. Please help me. I am new to web and have very little experience with JavaScript and php and just started on ajax. Your help will be much appreciated.
table_data.php (view)
bootbox.dialog({
message: '<div class="row"> ' +
'<div class="col-md-12"> ' +
'<form class="form-horizontal"> ' +
'<div class="form-group"> ' +
'<label class="col-md-4 control-label" for="awesomeness">Table ID: </label> ' +
'<div class="col-md-4">' +
'<input id="idtable" type="text" value="'+table_column_15+'"/>' +
'</div><br>' +
'</div>'+
'</form> </div> </div>',
title: "Form",
buttons: {
success: {
label: "Save",
className: "btn-success",
callback: function() {
console.log('save');
console.log($('#re_confirm')[0].checked);
var valueid = document.getElementById('idtable').value
if(valueid == 0)
myFunction();
var valueid2 = document.getElementById('idtable').value
if(valueid2==0)
return;
$.ajax({
url: "<?php echo base_url(); ?>index.php/home/check_occupied",
type: "post", // To protect sensitive data
data: {
"table_id" : valueid2
"session_id" : table_column_15
//and any other variables you want to pass via POST
},
success:function(response){
// Handle the response object
console.log(response);
var check = $(response);
}
});
if(check==0)
return;
$.ajax({
url : "<?php echo base_url(); ?>index.php/home/update_booking",
type: "post",
data: {
"table_id" : $('#idtable').val(),
},
success: function(response){
...
}
});
}
},
...
,
...
}
});
home_model.php (model)
public function check_occupied($tableid,$sessionid)
{
$sql = "SELECT * FROM booking WHERE table_id=$tableid and session=$sessionid;
$query = $this->db->query($sql);
if ($query->num_rows() > 0)
$imp = 1;
else
$imp = 0;
return $imp;
}
home.php(controller)
public function check_occupied()
{
$tableid = $_POST['table_id'];
$sessionid = $_POST['session_id'];
$imp = $this->home_model->check_occupied($tableid,$sessionid);
$this->load->view('table_data', $imp);
}
I found a few syntax minor errors but the biggest problem is where you are attempting to use the var check as in if(check==0).
Your condition evaluation if(check==0) is outside the success function of the ajax call to check_occupied. Therefore, if(check==0) will execute before the success function runs and sets a value for check. If you console.log(check); just before the if statement you will find the value to be 'undefined'. This console result will also be logged before the output of `console.log(response);' which will confirm the order of execution.
In other words, you need to decide on whether to run the next ajax call inside of the success function of the check_occupied ajax call.
Here's my version. It's untested but I think the concept is sound. This shows only the callback: for the "Save" button.
callback: function () {
console.log('save');
console.log($('#re_confirm')[0].checked);
var valueid = document.getElementById('idtable').value;
if (valueid === 0) {
myFunction();
}
var valueid2 = document.getElementById('idtable').value;
if (valueid2 === 0) {
return;
}
$.ajax({
url: "<?php echo base_url(); ?>index.php/home/check_occupied",
type: "post", // To protect sensitive data
data: {
"table_id": valueid2,
//??? where is table_column_15 declared and initialized? Some global var?
"session_id": table_column_15
//and any other variables you want to pass via POST
},
success: function (response) {
// Handle the response object
console.log('response='+response);
//if I read check_occupied() right, response should only be 1 or 0
//there is no need to assign it to another var, eg. var check = response
//there is no apparent need to turn it into a JQuery object with $(response) either
if (response > 0) {
$.ajax({
url: "<?php echo base_url(); ?>index.php/home/update_booking",
type: "post",
data: {
"table_id": $('#idtable').val()
},
success: function (response) {
}
});
}
}//end of success function callback for check_occupied() ajax
console.log('ajax to check_occupied is done.');
});
}

Using jquery blur with input having brackets[] with this.val and ajax together

This maybe easy for some of you, I'm have inputs with names with brackets, when the one gets a value I want to query the database using ajax to get the part number and put the value in the first empty pn[] field.
My HTML is:
<td>Record ID<span class="switchRed">*</span><br>
<input type="text" name="ri[]" id="ri" size="8" style="font-size:0.9em;" class="do_stuff"></td>
<td>Part Number<br>
<input type="text" name="pn[]" id="pn" style="font-size:0.9em;" class="readlock" readonly></td>
My Jquery / Ajax is
<script>
$(document).ready(function() {
$("[name='ri[]']").on("blur", "[name='ri[]']", function() {
var rival = $(this).val($(this).val());
$.ajax({
url: "/inventory/get-part-number.php",
type: "post",
data: "record=" + rival,
// callback for success
success: function(data, textStatus) {
$("[name='pn[]']").each(function() {
if(!$(this).val() ) {
$(this).val(data); //put value in empty pn[]
}//end if
})//End each
}, //end success else...
//if failsauce throw error
error: function() {
alert('Learn To Code');
} //end error failsauce
}); //ends .ajax function
}); //end blur
}); // ends ready function
</script>
The get-part-number.php is a simple mysql_query..
$message='';
if(isset($_POST['record'])){ $record_id = $_POST['record']; }else{$record_id='';}
//Get Part Number
$sql="SELECT p.part_number FROM parts p JOIN received r ON r.part_id=p.part_id WHERE r.received_id='$record_id'";
$query=mysql_query($sql) or die(mysql_error());
while($row=mysql_fetch_array($query)) {
$message.=$row['part_number'];
}
echo $message;
I have been un-succesfull in many variations to get the pn[] field to populate with results for the ajax request.
Can anybody see something wrong in my code and offer some advice.
Thank you
SOLUTION via smclark89 and Musa
Changed Jquery/Ajax from Above to:
<script>
$(document).ready(function() {
$("[name='ri[]']").on("blur", function() {
var rival = $(this).val();
$.ajax({
url: "/inventory/get-part-number.php",
type: "post",
data: "record=" + rival,
// callback for success
success: function(data, textStatus) {
$("[name='pn[]']").each(function() {
if(!$(this).val() ) {
$(this).val(data); //put value in empty pn[]
}//end if
})//End each
}, //end success else...
//if failsauce throw error
error: function() {
alert('Learn To Code');
} //end error failsauce
}); //ends .ajax function
}); //end blur
}); // ends ready function
</script>
When you're using .on for delegation, the element you bind to must be a container of the element you delegate to. So it should be:
$(document).on("blur", "input name='ri[]'", function() { ... });
You can substitute a more specific element for $(document) -- the only requirement is that this must be a static element that's an ancestor of the dynamic ri[] elements.

How to continuously update a part of the page

http://pastebin.com/dttyN3L6
The file that processes the form is called upload.php
I have never really used jquery/js so I am unsure how I would do this or where I would put the code.
It has something to do with this setInterval (loadLog, 2500);
Also, how can I make it so the user can submit a form without the page refreshing?
$.ajax({
type: "POST",
url: "upload.php",
data: dataString,
success: function() {
}
});
return false; `
and
<?php
$conn1 = mysqli_connect('xxx') or die('Error connecting to MySQL server.');
$sql = "SELECT * from text ORDER BY id DESC LIMIT 1";
$result = mysqli_query($conn1, $sql) or die('Error querying database.');
while ($row = mysqli_fetch_array($result)) {
echo '<p>' . $row['words'] . '</p>';
}
mysqli_close($conn1);
?>
</div>
<?php
if (!isset($_SESSION["user_id"])) {
} else {
require_once('form.php');
}
?>
You can submit a form without refreshing a page something like this:
form.php:
<form action='profile.php' method='post' class='ajaxform'>
<input type='text' name='txt' value='Test Text'>
<input type='submit' value='submit'>
</form>
<div id='result'>Result comes here..</div>
profile.php:
<?php
// All form data is in $_POST
// Now perform actions on form data here and
// create an result array something like this
$arr = array( 'result' => 'This is my result' );
echo json_encode( $arr );
?>
jQuery:
jQuery(document).ready(function(){
jQuery('.ajaxform').submit( function() {
$.ajax({
url : $(this).attr('action'),
type : $(this).attr('method'),
dataType: 'json',
data : $(this).serialize(),
success : function( data ) {
// loop to set the result(value)
// in required div(key)
for(var id in data) {
jQuery('#' + id).html( data[id] );
}
}
});
return false;
});
});
And If you want to call an ajax request without refreshing page after a particular time, you can try something like this:
var timer, delay = 300000;
timer = setInterval(function(){
$.ajax({
type : 'POST',
url : 'profile.php',
dataType: 'json',
data : $('.ajaxform').serialize(),
success : function(data){
for(var id in data) {
jQuery('#' + id).html( data[id] );
}
}
});
}, delay);
And you can stop the timer at any time like this:
clearInterval( timer );
Hope this will give you a direction to complete your task.
This is pretty simple.
To access elements using Jquery you use css selectors, for example, to get value of an input field with name "foo" you do the following:
var fooVal = $("input[name=foo]").val();
To send it over to the server you are to append an event listener (for example, click) to the submit button/any other element
var data = { varName : fooVal };
var url = "http://example.com";
var responseDataType = "json";
function parseResponse(JSON)
{
// your code handling server response here, it's called asynchronously, so you might want to add some indicator for the user, that your request is being processed
}
$("input[type=submit]").on('click', function(e){
e.preventDefault();
$(this).val("query processing");
$.post(url,data, parseResponse, responseDataType);
return false;
});
If you want to do constant updates, you can, of course, add timers or some other logic. But I hope you get the idea of how to proceed to such cases;
To answer part of your question, you can use ajax.
<html><head></head><body>
<div id="feed"></div>
<script type="text/javascript">
var refreshtime=10;
function tc()
{
asyncAjax("GET","upload.php",Math.random(),display,{});
setTimeout(tc,refreshtime);
}
function display(xhr,cdat)
{
if(xhr.readyState==4 && xhr.status==200)
{
document.getElementById("feed").innerHTML=xhr.responseText;
}
}
function asyncAjax(method,url,qs,callback,callbackData)
{
var xmlhttp=new XMLHttpRequest();
//xmlhttp.cdat=callbackData;
if(method=="GET")
{
url+="?"+qs;
}
var cb=callback;
callback=function()
{
var xhr=xmlhttp;
//xhr.cdat=callbackData;
var cdat2=callbackData;
cb(xhr,cdat2);
return;
}
xmlhttp.open(method,url,true);
xmlhttp.onreadystatechange=callback;
if(method=="POST"){
xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlhttp.send(qs);
}
else
{
xmlhttp.send(null);
}
}
tc();
</script>
</body></html>

Categories