I am currently working on a custom widget for Elementor and need to convert my Javascript functions into Ajax functions. My main issue has been figuring out how to pass variables from PHP to AJAX.
Here is the Javascript for the function in Question:
//Dynamic Price Calculator
$('#productQuant').keyup(function(){
// assign size from checked radio button
let productSize = $("input[type=radio][name=sizeRadio]:checked" ).val();
// assign quantity from values found in input text box
let productQuantity = $("#productQuant").val();
$.ajax({
// admin-ajax.php url
url: productDataAjax.url,
method: 'post',
dataType: 'json',
data:({
action: 'priceUpdate',
phpProductSize: productSize,
phpProductQuantity: productQuantity
}),
success:function(data){
console.log("Success");
// Text to product total
$('#productTotal').text(" " + data.dynamicTotal);
}
});
}); // function end
})( jQuery );
Here is the PHP:
/* Enque Scripts and Styles */
function shop_plugin_assets(){
// Enqueue CSS
wp_enqueue_style( 'bootstrap','https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css', array(), '1.0', 'all' );
// remeber array(), null at the end to mak sure googlefonts load. family = family = etc throws it off
wp_enqueue_style( 'google-font', 'https://fonts.googleapis.com/css2?family=Bungee&family=Sintony&display=swap', array(), null );
// Enqueue JQuery and JS Files
wp_enqueue_script( 'jquery');
wp_enqueue_script( 'bootstrap-bundle-js', 'https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js', array(), '1.0', true );
wp_enqueue_script( 'my-scripts', get_template_directory_uri() . '/js-custom/my-scripts.js', array( 'jquery' ), '1.0', true );
$script_data_array = array(
'ajaxUrl' => admin_url('admin-ajax.php'),
);
wp_localize_script('my-scripts', 'productDataAjax', $script_data_array);
}
add_action( 'wp_enqueue_scripts', 'shop_plugin_assets', 20 );
function dynamicPriceCalc(){
$productSize = $_POST['phpProductSize'];
$productQuantity = $_POST['phpProductQuantity'];
$productPrice = 0;
$productTotal = 0;
$response = array();
if( $productSize === "small"){
$productPrice = 7.99;
$productTotal = number_format( (float) ($productPrice * $productQuantity), 2, '.', '');
$response["dynamicTotal"] = $productTotal;
echo json_encode($response);
}
else if( $productSize === "medium"){
$productPrice = 10.99;
$productTotal = number_format( (float) ($productPrice * $productQuantity), 2, '.', '');
$response["dynamicTotal"] = $productTotal;
echo json_encode($response);
}
else if( $productSize === "large"){
$productPrice = 14.99;
$productTotal = number_format( (float) ($productPrice * $productQuantity), 2, '.', '');
$response["dynamicTotal"] = $productTotal;
echo json_encode($response);
}
die();
}
add_action('wp_ajax_priceUpdate', 'dynamicPriceCalc');
add_action('wp_ajax_nopriv_priceUpdate', 'dynamicPriceCalc');
Here is the Elementor widget File:
<?php
class Elementor_Custom_Product_Archive_Food extends \Elementor\Widget_Base {
public function get_name() {
return 'Custom Product Archive Food';
}
public function get_title() {
return esc_html__( 'Custom Product Archive Food Service', 'elementor-addon' );
}
public function get_icon() {
return 'eicon-code';
}
public function get_categories() {
return [ 'basic' ];
}
public function get_keywords() {
return [ 'archive', 'product', 'food' ];
}
// Controls for widgets
protected function register_controls()
{
$this->start_controls_section(
'button_section',
[
'label' => esc_html__( 'Product Archive Food', 'custom_product_archive_food' ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'button_align',
[
'label' => esc_html__( 'Alignment', 'custom_product_archive_food' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => [
'text-start' => [
'title' => esc_html__( 'Left', 'custom_product_archive_food' ),
'icon' => 'eicon-text-align-left',
],
'text-center' => [
'title' => esc_html__( 'Center', 'custom_product_archive_food' ),
'icon' => 'eicon-text-align-center',
],
'text-end' => [
'title' => esc_html__( 'Right', 'custom_product_archive_food' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'text-center',
'toggle' => true,
]
);
$this->end_controls_section();
} //end of controls
// Render the HTML and pulll data from controls to change classes or feed settings dynamic properties
protected function render() {
// settings pulls properties from control options to use within your html blocks
$settings = $this->get_settings_for_display();
$checkOutLink = wc_get_checkout_url();
// Radio Size selector
echo '<div class="text-center my-2">';
echo '<label> Choose a Size </label>';
echo '</div>';
echo '<div class="text-center mt-2" id="radioContainer">';
echo '<div class="form-check-inline">';
echo '<input class="form-check-input" type="radio" name="sizeRadio" id="smallRadio" value="small">';
echo '<label class="form-check-label" for="smallRadio">';
echo 'Small';
echo '</label>';
echo '</div>';
echo '<div class="form-check-inline">';
echo '<input class="form-check-input" type="radio" name="sizeRadio" id="medRadio" value="medium">';
echo '<label class="form-check-label" for="medRadio">';
echo 'Medium';
echo '</label>';
echo '</div>';
echo '<div class="form-check-inline">';
echo '<input class="form-check-input" type="radio" name="sizeRadio" id="largeRadio" value="large">';
echo '<label class="form-check-label" for="largeRadio">';
echo 'Large';
echo '</label>';
echo '</div>';
echo '</div>';
// Quantity / Logic Button / Redirect Button';
echo '<div class="text-center">';
echo '<div class="my-2">';
echo '<label id="productPrice"> Price: </label>';
echo '</div>';
echo '<input type="text" class="form-control input-group mt-3 w-25 mx-auto" placeholder="Enter Quantity" aria-label="Quantity" id="productQuant">';
echo '<div class="my-2">';
echo '<label id="productTotal"> Total:</label>';
echo '</div>';
echo '<button type="button" class="btn btn-lg btn-warning m-3 " name="button" id="addCartSubmit"> Add to Cart </button>';
echo '<a href="'.$checkOutLink.'" class="btn btn-lg btn-warning m-3"> Proceed to Check Out</a>';
echo '</div>';
} // End of protected functions
} //end of class
It is my understanding that I am supposed to call the PHP function using action while sending whatever data I pull with JQuery, execute the PHP function, make an array of the result within that function, encode the result in JSON, and on success have the JSON data inserted into whatever JQuery function I need it for.
For some reason, the function won't work even after trying several variations of the solution seen above. I know the logic works as I've recreated the same solution with pure JQuery and it works without a hitch. I know that there is some type of response going through as I get undefined and a console log of success when I remove the dataType:'json'. I don't know what is happening in between these two things that is stopping me from getting the label change to reflect my new product total.
Some Images After Inputting Text into the Text Field. You'll notice the Total section remains blank:
Header Request showing it accepts Javascript and JSON
Response showing HTML - I think I need it to return JSON here